diff --git a/.dockerignore b/.dockerignore
index 8af5ccea0..87bc53fe0 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -2,3 +2,4 @@
*.pyc
**/*.pyc
Dockerfile
+*venv*
diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml
index 2c77176e0..4c9ac40d7 100644
--- a/.github/workflows/test-build.yml
+++ b/.github/workflows/test-build.yml
@@ -5,59 +5,71 @@ on: [push, pull_request, workflow_dispatch]
jobs:
build:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-24.04
env:
- GHA_DISTRO: ubuntu-20.04
+ GHA_DISTRO: ubuntu-24.04
if: "!contains(github.event.head_commit.message, 'skip ci')"
strategy:
matrix:
- python-version: [3.6]
+ python-version: [3.13]
steps:
- name: Git checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
+
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
+
- name: Cache Build Requirements
id: pip-cache-step
- uses: actions/cache@v2
+ uses: actions/cache@v4
with:
- path: ${{ env.pythonLocation }}
- key: ${{ env.GHA_DISTRO }}-${{ env.pythonLocation }}-${{ hashFiles('requirements.txt', 'dev-requirements.txt') }}
- - name: install dependencies
- if: steps.pip-cache-step.outputs.cache-hit != 'true'
+ path: ~/.cache/pip
+ key: ${{ env.GHA_DISTRO }}-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml', 'poetry.lock') }}
+
+ - name: Install dependencies
run: |
- python -m pip install --upgrade pip
- pip install -r dev-requirements.txt
+ python -m pip install poetry==2.1.2 setuptools==80.1.0
+ poetry install --no-root --without=docs --with=dev
runtests:
name: Run unit tests
needs: build
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-24.04
env:
- GHA_DISTRO: ubuntu-20.04
+ GHA_DISTRO: ubuntu-24.04
+ strategy:
+ matrix:
+ python-version: [3.13]
steps:
- - uses: actions/checkout@v2
- - name: Set up Python 3.6
- uses: actions/setup-python@v2
+ - uses: actions/checkout@v3
+
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v4
with:
- python-version: 3.6
+ python-version: ${{ matrix.python-version }}
+
- name: Cache pip
- uses: actions/cache@v2
+ uses: actions/cache@v4
with:
- path: ${{ env.pythonLocation }}
- key: ${{ env.GHA_DISTRO }}-${{ env.pythonLocation }}-${{ hashFiles('requirements.txt', 'dev-requirements.txt') }}
- - name: run syntax checks
- run: |
- flake8 .
- - name: build plugins
+ path: ~/.cache/pip
+ key: ${{ env.GHA_DISTRO }}-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml', 'poetry.lock') }}
+
+ - name: Install test dependencies
run: |
- python setup.py develop
- - name: run unit tests
+ python -m pip install poetry==2.1.2
+ python -m pip install setuptools==80.1.0
+ poetry install --without=docs --with=dev
+
+ - name: Run flake8
+ run: poetry run flake8 .
+
+ - name: Run unit tests
run: |
- py.test --cov-report term-missing --cov mfr tests
- - name: Upload coverage data to coveralls.io
- run: coveralls --service=github
+ poetry run pytest --cov-report term-missing --cov mfr tests
+
+ - name: Upload coverage to Coveralls
+ run: poetry run coveralls --service=github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/Dockerfile b/Dockerfile
index f73f5c93e..a835215d6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,17 +1,12 @@
-FROM python:3.6-slim-buster
+FROM python:3.13-slim
-# ensure unoconv can locate the uno library
-ENV PYTHONPATH /usr/lib/python3/dist-packages
RUN usermod -d /home www-data \
&& chown www-data:www-data /home \
- # -slim images strip man dirs, but java won't install unless this dir exists.
- && mkdir -p /usr/share/man/man1 \
- && apt-get update \
- # HACK: work around bug in install java (dep of libreoffice)
- && apt-get install -y ca-certificates-java \
+ && apt-get update
+
# mfr dependencies
- && apt-get install -y \
+RUN apt-get install -y \
git \
make \
gcc \
@@ -32,32 +27,31 @@ RUN usermod -d /home www-data \
freecad \
# pspp dependencies
pspp \
- # unoconv dependencies
- libreoffice \
# grab gosu for easy step-down from root
- gosu \
- && apt-get clean \
- && apt-get autoremove -y \
- && rm -rf /var/lib/apt/lists/*
+ gosu
+RUN apt-get clean
+RUN apt-get autoremove -y
+RUN rm -rf /var/lib/apt/lists/*
RUN mkdir -p /code
WORKDIR /code
-RUN pip install -U pip==18.1
-RUN pip install setuptools==37.0.0
-RUN pip install unoconv==0.8.2
+COPY pyproject.toml poetry.lock* /code/
-COPY ./requirements.txt /code/
+ENV POETRY_NO_INTERACTION=1 \
+ POETRY_VIRTUALENVS_CREATE=0 \
+ POETRY_VIRTUALENVS_IN_PROJECT=1
-RUN pip install --no-cache-dir -r ./requirements.txt
+RUN pip install poetry==2.1.2 setuptools==80.1.0 \
+ && poetry install --no-root --without=docs
# Copy the rest of the code over
COPY ./ /code/
ARG GIT_COMMIT=
-ENV GIT_COMMIT ${GIT_COMMIT}
+ENV GIT_COMMIT=${GIT_COMMIT}
-RUN python setup.py develop
+RUN poetry install --without=docs
EXPOSE 7778
diff --git a/README.md b/README.md
index c8bb4b69b..718bf84f0 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ A Python package for rendering files to HTML via an embeddable iframe.
### Compatibility
-MFR is compatible with Python 3.6.
+MFR is compatible with Python 3.13.
### Documentation
@@ -16,35 +16,32 @@ Documentation available at: http://modular-file-renderer.readthedocs.io/en/lates
### Setting up
-Install the latest version of python3.6.
+Install the latest version of python3.13.
For MacOSX users:
```bash
-brew install python3
+brew install python@3.13
# optional, needed for some converters
-brew install pspp unoconv
+brew install pspp libreoffice
```
For Ubuntu users:
```bash
-apt-get install python3
+apt-get install python3.13
# optional, needed for some converters
-apt-get install pspp unoconv
+apt-get install pspp libreoffice
```
-After installing python3.6, create the virtual environment with the following commands:
+After installing python3.13, set up the project with the following commands:
```bash
-pip install virtualenv
-pip install virtualenvwrapper
-mkvirtualenv --python=`which python3.6` mfr
+pip install poetry
+poetry env use python3.13
+poetry install
-pip install setuptools==37.0.0
-pip install invoke==0.13.0
-
-invoke install
-invoke server
+poetry run invoke install
+poetry run invoke server
```
### Configuring
@@ -80,8 +77,8 @@ If you encounter the error message `TypeError: throw() takes 2 positional argume
Before running the tests, you will need to install some additional requirements. In your checkout, run:
```bash
-invoke install --develop
-invoke test
+poetry run invoke install --develop
+poetry run invoke test
```
### Known issues
@@ -98,7 +95,7 @@ Interested in adding support for a new provider or file format? Check out the CO
### License
-Copyright 2013-2023 Center for Open Science
+Copyright 2013-2025 Center for Open Science
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/constraints.txt b/constraints.txt
deleted file mode 100644
index b4cc80a02..000000000
--- a/constraints.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-## Constraints file for resolving conflicts across packages. Used to resolve issues with sub-dependencies of an actual requirement.
-## (eg when python-coveralls indirectly requires a version of requests)
-## "Constraints files are requirements files that only control which version of a requirement is installed, not whether it is installed or not."
-## See https://pip-python3.readthedocs.org/en/latest/user_guide.html#constraints-files
-
-# Newer version of requests throw an error when using the version of chardet we pin to; this causes issues for python-coveralls
-requests==2.14.2
diff --git a/dev-requirements.txt b/dev-requirements.txt
deleted file mode 100644
index 37036c257..000000000
--- a/dev-requirements.txt
+++ /dev/null
@@ -1,16 +0,0 @@
--r requirements.txt
-
-# aiohttpretty disabled due to no usage in MFR, re-enable when needed
-# git+https://github.com/centerforopenscience/aiohttpretty.git@0.1.0#egg=aiohttpretty
-
-beautifulsoup4
-colorlog==2.5.0
-coveralls
-flake8==3.0.4
-ipdb
-mccabe
-pydevd==0.0.6
-pyflakes
-pytest==2.8.2
-pytest-cov==2.2.0
-pyzmq==14.4.1
diff --git a/doc-requirements.txt b/doc-requirements.txt
deleted file mode 100644
index e79b57f30..000000000
--- a/doc-requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-sphinx-rtd-theme
-sphinx
-sphinx-autobuild
diff --git a/docs/conf.py b/docs/conf.py
index 42c804545..2babd0c03 100755
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# MFR documentation build configuration file.
#
@@ -31,7 +30,7 @@
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'stevedore.sphinxext']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -46,8 +45,8 @@
master_doc = 'index'
# General information about the project.
-project = u'mfr'
-copyright = u'2023, Center For Open Science'
+project = 'mfr'
+copyright = '2025, Center For Open Science'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -177,12 +176,7 @@
# Output file base name for HTML help builder.
htmlhelp_basename = 'mfrdoc'
+# This block will use the same theme when building locally as on RTD.
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
-
-# On RTD we can't import sphinx_rtd_theme, but it will be applied by
-# default anyway. This block will use the same theme when building locally
-# as on RTD.
if not on_rtd:
- import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
- html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
diff --git a/docs/extensions.rst b/docs/extensions.rst
index e6a529310..dea5a779b 100644
--- a/docs/extensions.rst
+++ b/docs/extensions.rst
@@ -11,11 +11,6 @@ CodePygmentsRenderer
.. autoclass:: mfr.extensions.codepygments.CodePygmentsRenderer
-DocxRenderer
-------------
-
-.. autoclass:: mfr.extensions.docx.DocxRenderer
-
ImageExporter
-------------
diff --git a/docs/index.rst b/docs/index.rst
index b2ef4f7bf..fdf82f1c5 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -26,6 +26,7 @@ Guide
overview
integrations
code
+ plugins
Project info
------------
diff --git a/docs/install.rst b/docs/install.rst
index d26d82fa2..913c8e4de 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -14,26 +14,25 @@ Or download one of the following:
* tarball_
* zipball_
-Make sure that you have installed `pspp `_ and are using python 3.5 or greater.
+Make sure that you have installed `pspp `_ and are using python v3.13 or greater.
-Install the versions of ``setuptools`` and ``invoke`` found in the requirements.txt file:
+Install ``poetry`` to manage dependencies:
.. code-block:: bash
- pip install setuptools==37.0.0
- pip install invoke==0.13.0
+ pip install poetry==2.1.2
Install requirements:
.. code-block:: bash
- invoke install
+ poetry install
Or for some nicities (like tests):
.. code-block:: bash
- invoke install --develop
+ poetry install --with dev
Start the server:
@@ -45,7 +44,7 @@ Start the server:
.. code-block:: bash
- invoke server
+ poetry run invoke server
.. _Github: https://github.com/CenterForOpenScience/modular-file-renderer
.. _tarball: https://github.com/CenterForOpenScience/modular-file-renderer/tarball/master
diff --git a/docs/plugins.rst b/docs/plugins.rst
new file mode 100644
index 000000000..05e75afaa
--- /dev/null
+++ b/docs/plugins.rst
@@ -0,0 +1,20 @@
+
+Plugins
+-------
+
+Auth Providers
+==============
+
+.. list-plugins:: mfr.providers
+ :detailed:
+
+Exporters
+=========
+
+.. list-plugins:: mfr.exporters
+
+Renderers
+=========
+
+.. list-plugins:: mfr.renderers
+
diff --git a/mfr/__init__.py b/mfr/__init__.py
old mode 100755
new mode 100644
index 202301093..e69de29bb
--- a/mfr/__init__.py
+++ b/mfr/__init__.py
@@ -1,4 +0,0 @@
-# This is a namespace package, don't put any functional code in here besides the
-# declare_namespace call, or it will disappear on install. See:
-# https://setuptools.readthedocs.io/en/latest/setuptools.html#namespace-packages
-__import__('pkg_resources').declare_namespace(__name__)
diff --git a/mfr/core/exceptions.py b/mfr/core/exceptions.py
index 8f3573b54..bfc9fc953 100644
--- a/mfr/core/exceptions.py
+++ b/mfr/core/exceptions.py
@@ -26,7 +26,8 @@ def as_html(self):
free, open source software? Check out our openings!
'''.format(self.message)
- def _format_original_exception(self, exc):
+ @staticmethod
+ def _format_original_exception(exc):
"""Sometimes we catch an error from an external library, but would like to throw our own
error instead. This method will take in an external error class and format it for
consistent representation in the error metrics.
@@ -45,7 +46,7 @@ class ExtensionError(PluginError):
__TYPE = 'extension'
- def __init__(self, message, *args, extension: str='', **kwargs):
+ def __init__(self, message, *args, extension: str = '', **kwargs):
super().__init__(message, *args, **kwargs)
self.extension = extension
self.attr_stack.append([self.__TYPE, {'extension': self.extension}])
@@ -58,7 +59,7 @@ class RendererError(ExtensionError):
__TYPE = 'renderer'
- def __init__(self, message, *args, renderer_class: str='', **kwargs):
+ def __init__(self, message, *args, renderer_class: str = '', **kwargs):
super().__init__(message, *args, **kwargs)
self.renderer_class = renderer_class
self.attr_stack.append([self.__TYPE, {'class': self.renderer_class}])
@@ -71,7 +72,7 @@ class ExporterError(ExtensionError):
__TYPE = 'exporter'
- def __init__(self, message, *args, exporter_class: str='', **kwargs):
+ def __init__(self, message, *args, exporter_class: str = '', **kwargs):
super().__init__(message, *args, **kwargs)
self.exporter_class = exporter_class
self.attr_stack.append([self.__TYPE, {'exporter_class': self.exporter_class}])
@@ -84,8 +85,8 @@ class SubprocessError(ExporterError):
__TYPE = 'subprocess'
- def __init__(self, message, *args, code: int=500, process: str='', cmd: str='',
- returncode: int=None, path: str='', **kwargs):
+ def __init__(self, message, *args, code: int = 500, process: str = '', cmd: str = '',
+ returncode: int = None, path: str = '', **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.process = process
self.cmd = cmd
@@ -106,7 +107,7 @@ class ProviderError(PluginError):
__TYPE = 'provider'
- def __init__(self, message, *args, provider: str='', **kwargs):
+ def __init__(self, message, *args, provider: str = '', **kwargs):
super().__init__(message, *args, **kwargs)
self.provider = provider
self.attr_stack.append([self.__TYPE, {'provider': self.provider}])
@@ -119,7 +120,7 @@ class DownloadError(ProviderError):
__TYPE = 'download'
- def __init__(self, message, *args, download_url: str='', response: str='', **kwargs):
+ def __init__(self, message, *args, download_url: str = '', response: str = '', **kwargs):
super().__init__(message, *args, **kwargs)
self.download_url = download_url
self.response = response
@@ -136,7 +137,7 @@ class MetadataError(ProviderError):
__TYPE = 'metadata'
- def __init__(self, message, *args, metadata_url: str='', response: str='', **kwargs):
+ def __init__(self, message, *args, metadata_url: str = '', response: str = '', **kwargs):
super().__init__(message, *args, **kwargs)
self.metadata_url = metadata_url
self.response = response
@@ -145,6 +146,13 @@ def __init__(self, message, *args, metadata_url: str='', response: str='', **kwa
'response': self.response
}])
+class CorruptedError(RendererError):
+
+ __TYPE = 'corrupted'
+
+ def __init__(self, *args, renderer_class: str = '', **kwargs):
+ super().__init__("File is corrupted, impossible to render, please check it's integrity", *args, renderer_class, **kwargs)
+
class TooBigToRenderError(ProviderError):
"""If the user tries to render a file larger than a server specified maximum, throw a
TooBigToRenderError.
@@ -152,8 +160,8 @@ class TooBigToRenderError(ProviderError):
__TYPE = 'too_big_to_render'
- def __init__(self, message, *args, requested_size: int=None, maximum_size: int=None,
- code: int=400, **kwargs):
+ def __init__(self, message, *args, requested_size: int = None, maximum_size: int = None,
+ code: int = 400, **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.requested_size = requested_size
self.maximum_size = maximum_size
@@ -167,8 +175,8 @@ class DriverManagerError(PluginError):
__TYPE = 'drivermanager'
- def __init__(self, message, *args, namespace: str='', name: str='', invoke_on_load: bool=None,
- invoke_args: dict=None, **kwargs):
+ def __init__(self, message, *args, namespace: str = '', name: str = '', invoke_on_load: bool = None,
+ invoke_args: dict = None, **kwargs):
super().__init__(message, *args, **kwargs)
self.namespace = namespace
@@ -188,7 +196,7 @@ class MakeProviderError(DriverManagerError):
"""Thrown when MFR can't find an applicable provider class. This indicates programmer error,
so ``code`` defaults to ``500``."""
- def __init__(self, message, *args, code: int=500, **kwargs):
+ def __init__(self, message, *args, code: int = 500, **kwargs):
super().__init__(message, *args, code=code, **kwargs)
@@ -200,7 +208,7 @@ class UnsupportedExtensionError(DriverManagerError):
__TYPE = 'unsupported_extension'
- def __init__(self, *args, code: int=400, handler_type: str='', **kwargs):
+ def __init__(self, *args, code: int = 400, handler_type: str = '', **kwargs):
super().__init__(*args, code=code, **kwargs)
self.handler_type = handler_type
diff --git a/mfr/core/extension.py b/mfr/core/extension.py
index 928cf2224..a2f202d5a 100644
--- a/mfr/core/extension.py
+++ b/mfr/core/extension.py
@@ -1,6 +1,15 @@
import abc
+import asyncio
+import time
+from dataclasses import dataclass, field
+from waterbutler.core.streams import StringStream
+from waterbutler.core.utils import make_provider
+
+from mfr.server import settings
from mfr.core.metrics import MetricsRecord
+from mfr.core.provider import ProviderMetadata
+from mfr.tasks.serializer import serializable
class BaseExporter(metaclass=abc.ABCMeta):
@@ -42,19 +51,28 @@ def _get_module_name(self):
.replace('mfr.extensions.', '', 1) \
.replace('.export', '', 1)
-
+@serializable
+@dataclass
class BaseRenderer(metaclass=abc.ABCMeta):
-
- def __init__(self, metadata, file_path, url, assets_url, export_url):
- self.metadata = metadata
- self.file_path = file_path
- self.url = url
- self.assets_url = '{}/{}'.format(assets_url, self._get_module_name())
- self.export_url = export_url
- self.renderer_metrics = MetricsRecord('renderer')
+ metadata: ProviderMetadata
+ file_path: str
+ url: str
+ assets_url: str
+ export_url: str
+ renderer_metrics: MetricsRecord = field(default=None)
+ metrics: MetricsRecord = field(default=None)
+
+ def __post_init__(self):
+ self.assets_url = f'{self.assets_url}/{self._get_module_name()}'
+ self.renderer_metrics = MetricsRecord('renderer',)
if self._get_module_name():
self.metrics = self.renderer_metrics.new_subrecord(self._get_module_name())
+ if name := self.metadata.name:
+ self.cache_file_path_str = f'/export/{self.metadata.unique_key}.{name}'
+ else:
+ self.cache_file_path_str = f'/export/{self.metadata.unique_key}'
+
self.renderer_metrics.merge({
'class': self._get_module_name(),
'ext': self.metadata.ext,
@@ -73,11 +91,56 @@ def __init__(self, metadata, file_path, url, assets_url, export_url):
except AttributeError:
pass
+ @property
+ def cache_provider(self):
+ return make_provider(
+ settings.CACHE_PROVIDER_NAME,
+ {}, # User information which can be left blank
+ settings.CACHE_PROVIDER_CREDENTIALS,
+ settings.CACHE_PROVIDER_SETTINGS
+ )
+
+ async def get_cache_file_path(self):
+ return await self.cache_provider.validate_path(self.cache_file_path_str)
+
@abc.abstractmethod
- def render(self):
+ def _render(self) -> str:
pass
- @abc.abstractproperty
+ async def render(self):
+ if self.use_celery or self.cache_result:
+ self.cache_file_path = await self.cache_provider.validate_path(self.cache_file_path_str)
+ if not self.use_celery:
+ rendition = await self.do_render()
+ return StringStream(rendition)
+ else:
+ from mfr.tasks.render import render
+ result = render.delay(self)
+ for i in range(100 * 60 * 10):
+ if not result.ready():
+ time.sleep(0.01)
+ else:
+ return await self.cache_provider.download(self.cache_file_path)
+
+ return None
+
+ async def do_render(self):
+ if self.use_celery or self.cache_result:
+ file_path_task = asyncio.ensure_future(self.get_cache_file_path())
+ rendition = await asyncio.get_running_loop().run_in_executor(None, self._render)
+ if self.use_celery or self.cache_result:
+ upload_task = asyncio.ensure_future(
+ self.cache_provider.upload(
+ StringStream(rendition),
+ await file_path_task
+ )
+ )
+ if self.use_celery:
+ await upload_task
+ return rendition
+
+ @property
+ @abc.abstractmethod
def file_required(self):
"""Does the rendering html need the raw file content to display correctly?
Syntax-highlighted text files do. Standard image formats do not, since an
tag
@@ -85,10 +148,15 @@ def file_required(self):
"""
pass
- @abc.abstractproperty
- def cache_result(self):
+ @property
+ @abc.abstractmethod
+ def cache_result(self) -> bool:
pass
+ @property
+ def use_celery(self) -> bool:
+ return False
+
def _get_module_name(self):
return self.__module__ \
.replace('mfr.extensions.', '', 1) \
diff --git a/mfr/core/metrics.py b/mfr/core/metrics.py
index bf47eee25..bc80819e5 100644
--- a/mfr/core/metrics.py
+++ b/mfr/core/metrics.py
@@ -1,4 +1,7 @@
import copy
+from dataclasses import dataclass, field
+
+from mfr.tasks.serializer import serializable
def _merge_dicts(a, b, path=None):
@@ -22,7 +25,7 @@ def _merge_dicts(a, b, path=None):
return a
-class MetricsBase():
+class MetricsBase:
"""Lightweight wrapper around a dict to make keeping track of metrics a little easier.
Current functionality is limited, but may be extended later. To do:
@@ -77,7 +80,8 @@ def manifesto(self):
"""
return {self.key: self.serialize()}
- def _set_dotted_key(self, store, key, value):
+ @staticmethod
+ def _set_dotted_key(store, key, value):
"""Naive method to set nested dict values via dot-separated keys. e.g
``_set_dotted_keys(self._metrics, 'foo.bar', 'moo')`` is equivalent to
``self._metrics['foo']['bar'] = 'moo'``. This method is neither resilient nor intelligent
@@ -92,16 +96,17 @@ def _set_dotted_key(self, store, key, value):
current = current[part]
current[parts[-1]] = value
-
+@serializable
+@dataclass
class MetricsRecord(MetricsBase):
"""An extension to MetricsBase that carries a category and list of submetrics. When
serialized, will include the serialized child metrics
"""
+ category: str
+ subrecords: list = field(default_factory=list)
- def __init__(self, category):
+ def __post_init__(self):
super().__init__()
- self.category = category
- self.subrecords = []
@property
def key(self):
@@ -120,25 +125,28 @@ def serialize(self):
def new_subrecord(self, name):
"""Create a new MetricsSubRecord object with our category and save it to the subrecords
list."""
- subrecord = MetricsSubRecord(self.category, name)
+ subrecord = MetricsSubRecord(category=self.category, name=name)
self.subrecords.append(subrecord)
return subrecord
-
+@serializable
+@dataclass
class MetricsSubRecord(MetricsRecord):
"""An extension to MetricsRecord that carries a name in addition to a category. Will identify
itself as {category}_{name}. Can create its own subrecord whose category will be this
subrecord's ``name``.
"""
+ name: str = field(default=None)
- def __init__(self, category, name):
- super().__init__(category)
- self.name = name
+ def __post_init__(self):
+ super().__post_init__()
+ if self.name is None:
+ raise TypeError('name must be provided')
@property
def key(self):
"""ID string for this subrecord: '{category}_{name}'"""
- return '{}_{}'.format(self.category, self.name)
+ return f'{self.category}_{self.name}'
def new_subrecord(self, name):
"""Creates and saves a new subrecord. The new subrecord will have its category set to the
@@ -152,6 +160,6 @@ def new_subrecord(self, name):
print(child.key) # foo_bar
print(grandchild.key) # bar_baz
"""
- subrecord = MetricsSubRecord(self.name, name)
+ subrecord = MetricsSubRecord(category=self.name, name=name)
self.subrecords.append(subrecord)
return subrecord
diff --git a/mfr/core/provider.py b/mfr/core/provider.py
index dac7c0f62..33fc705b9 100644
--- a/mfr/core/provider.py
+++ b/mfr/core/provider.py
@@ -1,4 +1,6 @@
import abc
+from dataclasses import dataclass
+
import markupsafe
import furl
@@ -6,6 +8,7 @@
from mfr.core import exceptions
from mfr.server import settings
from mfr.core.metrics import MetricsRecord
+from mfr.tasks.serializer import serializable
class BaseProvider(metaclass=abc.ABCMeta):
@@ -34,8 +37,9 @@ def __init__(self, request, url, action=None):
'url': str(self.url),
})
- @abc.abstractproperty
+ @abc.abstractmethod
def NAME(self):
+ # Todo: not see Name implementation in child classes
raise NotImplementedError
@abc.abstractmethod
@@ -46,16 +50,15 @@ def metadata(self):
def download(self):
pass
-
+@serializable
+@dataclass
class ProviderMetadata:
-
- def __init__(self, name, ext, content_type, unique_key, download_url, stable_id=None):
- self.name = name
- self.ext = ext
- self.content_type = content_type
- self.unique_key = unique_key
- self.download_url = download_url
- self.stable_id = stable_id
+ name: str
+ ext: str
+ content_type: str
+ unique_key: str
+ download_url: str
+ stable_id: str = None
def serialize(self):
return {
diff --git a/mfr/core/remote_logging.py b/mfr/core/remote_logging.py
index bdde5446f..d7460c584 100644
--- a/mfr/core/remote_logging.py
+++ b/mfr/core/remote_logging.py
@@ -78,16 +78,13 @@ async def log_analytics(request, metrics, is_error=False):
# send the private payload
private_collection = 'mfr_errors' if is_error else 'mfr_action'
- if ((is_error and settings.KEEN_PRIVATE_LOG_ERRORS) or settings.KEEN_PRIVATE_LOG_VIEWS):
+ if (is_error and settings.KEEN_PRIVATE_LOG_ERRORS) or settings.KEEN_PRIVATE_LOG_VIEWS:
await _send_to_keen(keen_payload, private_collection, settings.KEEN_PRIVATE_PROJECT_ID,
settings.KEEN_PRIVATE_WRITE_KEY, keen_payload['handler']['type'],
domain='private')
if (
- keen_payload['handler']['type'] != 'render' or
- file_metadata is None or
- is_error or
- not settings.KEEN_PUBLIC_LOG_VIEWS
+ keen_payload['handler']['type'] != 'render' or file_metadata is None or is_error or not settings.KEEN_PUBLIC_LOG_VIEWS
):
return
@@ -104,18 +101,18 @@ async def _send_to_keen(payload, collection, project_id, write_key, action, doma
Will raise an excpetion if the event cannot be sent."""
serialized = json.dumps(payload).encode('UTF-8')
- logger.debug("Serialized payload: {}".format(serialized))
+ logger.debug(f"Serialized payload: {serialized}")
headers = {
'Content-Type': 'application/json',
'Authorization': write_key,
}
- url = '{0}/{1}/projects/{2}/events/{3}'.format(settings.KEEN_API_BASE_URL,
+ url = '{}/{}/projects/{}/events/{}'.format(settings.KEEN_API_BASE_URL,
settings.KEEN_API_VERSION,
project_id, collection)
- async with await aiohttp.request('POST', url, headers=headers, data=serialized) as resp:
+ async with aiohttp.request('POST', url, headers=headers, data=serialized) as resp:
if resp.status == 201:
- logger.info('Successfully logged {} to {} collection in {} Keen'.format(action, collection, domain))
+ logger.info(f'Successfully logged {action} to {collection} collection in {domain} Keen')
else:
raise Exception('Failed to log {} to {} collection in {} Keen. Status: {} Error: {}'.format(
action, collection, domain, str(int(resp.status)), await resp.read()
@@ -133,7 +130,7 @@ def _scrub_headers_for_keen(payload, MAX_ITERATIONS=10):
# if our new scrubbed key is already in the payload, we need to increment it
if scrubbed_key in scrubbed_payload:
for i in range(1, MAX_ITERATIONS + 1): # try MAX_ITERATION times, then give up & drop it
- incremented_key = '{}-{}'.format(scrubbed_key, i)
+ incremented_key = f'{scrubbed_key}-{i}'
if incremented_key not in scrubbed_payload: # we found an unused key!
scrubbed_payload[incremented_key] = payload[key]
break
diff --git a/mfr/core/utils.py b/mfr/core/utils.py
index 52ae1c2b8..163093721 100644
--- a/mfr/core/utils.py
+++ b/mfr/core/utils.py
@@ -1,4 +1,4 @@
-import pkg_resources
+from importlib.metadata import entry_points
from stevedore import driver
from mfr.core import exceptions
@@ -10,6 +10,7 @@ def make_provider(name, request, url, action=None):
:param str name: The name of the provider to instantiate. (osf)
:param request:
:param dict url:
+ :param action:
:rtype: :class:`mfr.core.provider.BaseProvider`
"""
@@ -23,7 +24,7 @@ def make_provider(name, request, url, action=None):
).driver
except RuntimeError:
raise exceptions.MakeProviderError(
- '"{}" is not a supported provider'.format(name.lower()),
+ f'"{name.lower()}" is not a supported provider',
namespace='mfr.providers',
name=name.lower(),
invoke_on_load=True,
@@ -33,24 +34,39 @@ def make_provider(name, request, url, action=None):
}
)
-
-def make_exporter(name, source_file_path, output_file_path, format, metadata):
+def fix_name(name: str):
+ name = name.removeprefix('.').replace('+', 'p')
+ if name == 'lasso[89]':
+ return 'lasso'
+ elif name == 'php[345]':
+ return 'php'
+ elif name == 'css.in':
+ return 'css'
+ elif name == 'js.in':
+ return 'js'
+ elif name == 'xul.in':
+ return 'xul'
+ return name
+
+def make_exporter(name, source_file_path, output_file_path, file_format, metadata):
"""Returns an instance of :class:`mfr.core.extension.BaseExporter`
:param str name: The name of the extension to instantiate. (.jpg, .docx, etc)
:param str source_file_path:
:param str output_file_path:
- :param str format:
+ :param str file_format:
+ :param metadata:
:rtype: :class:`mfr.core.extension.BaseExporter`
"""
- normalized_name = (name and name.lower()) or 'none'
+ normalized_name = fix_name(name and name.lower()) or 'none'
+
try:
return driver.DriverManager(
namespace='mfr.exporters',
name=normalized_name,
invoke_on_load=True,
- invoke_args=(normalized_name, source_file_path, output_file_path, format, metadata),
+ invoke_args=(normalized_name, source_file_path, output_file_path, file_format, metadata),
).driver
except RuntimeError:
raise exceptions.MakeExporterError(
@@ -60,7 +76,7 @@ def make_exporter(name, source_file_path, output_file_path, format, metadata):
invoke_args={
'source_file_path': source_file_path,
'output_file_path': output_file_path,
- 'format': format,
+ 'format': file_format,
}
)
@@ -70,6 +86,7 @@ def make_renderer(name, metadata, file_path, url, assets_url, export_url):
:param str name: The name of the extension to instantiate. (.jpg, .docx, etc)
:param: :class:`mfr.core.provider.ProviderMetadata` metadata:
+ :param metadata:
:param str file_path:
:param str url:
:param str assets_url:
@@ -77,13 +94,19 @@ def make_renderer(name, metadata, file_path, url, assets_url, export_url):
:rtype: :class:`mfr.core.extension.BaseRenderer`
"""
- normalized_name = (name and name.lower()) or 'none'
+ normalized_name = fix_name(name and name.lower()) or 'none'
try:
return driver.DriverManager(
namespace='mfr.renderers',
name=normalized_name,
invoke_on_load=True,
- invoke_args=(metadata, file_path, url, assets_url, export_url),
+ invoke_kwds={
+ 'metadata': metadata,
+ 'file_path': file_path,
+ 'url': url,
+ 'assets_url': assets_url,
+ 'export_url': export_url
+ },
).driver
except RuntimeError:
raise exceptions.MakeRendererError(
@@ -110,8 +133,8 @@ def get_renderer_name(name: str) -> str:
# `ep_iterator` is an iterable object. Must convert it to a `list` for access.
# `list()` can only be called once because the iterator moves to the end after conversion.
- ep_iterator = pkg_resources.iter_entry_points(group='mfr.renderers', name=name.lower())
- ep_list = list(ep_iterator)
+ ep = entry_points().select(group='mfr.renderers', name=name.lower())
+ ep_list = list(ep)
# Empty list indicates unsupported file type. Return '' and let `make_renderer()` handle it.
if len(ep_list) == 0:
@@ -119,7 +142,7 @@ def get_renderer_name(name: str) -> str:
# If the file type is supported, there must be only one element in the list.
assert len(ep_list) == 1
- return ep_list[0].attrs[0]
+ return ep_list[0].value.split(":")[-1]
def get_exporter_name(name: str) -> str:
@@ -132,8 +155,8 @@ def get_exporter_name(name: str) -> str:
# `ep_iterator` is an iterable object. Must convert it to a `list` for access.
# `list()` can only be called once because the iterator moves to the end after conversion.
- ep_iterator = pkg_resources.iter_entry_points(group='mfr.exporters', name=name.lower())
- ep_list = list(ep_iterator)
+ ep = entry_points().select(group='mfr.exporters', name=name.lower())
+ ep_list = list(ep)
# Empty list indicates unsupported export type. Return '' and let `make_exporter()` handle it.
if len(ep_list) == 0:
@@ -141,15 +164,15 @@ def get_exporter_name(name: str) -> str:
# If the export type is supported, there must be only one element in the list.
assert len(ep_list) == 1
- return ep_list[0].attrs[0]
+ return ep_list[0].value.split(":")[-1]
def sizeof_fmt(num, suffix='B'):
if abs(num) < 1000:
- return '%3.0f%s' % (num, suffix)
+ return '{:3.0f}{}'.format(num, suffix)
for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
if abs(num) < 1000.0:
- return '%3.1f%s%s' % (num, unit, suffix)
+ return '{:3.1f}{}{}'.format(num, unit, suffix)
num /= 1000.0
- return '%.1f%s%s' % (num, 'Y', suffix)
+ return '{:.1f}{}{}'.format(num, 'Y', suffix)
diff --git a/mfr/extensions/__init__.py b/mfr/extensions/__init__.py
index de40ea7ca..e69de29bb 100644
--- a/mfr/extensions/__init__.py
+++ b/mfr/extensions/__init__.py
@@ -1 +0,0 @@
-__import__('pkg_resources').declare_namespace(__name__)
diff --git a/mfr/extensions/audio/render.py b/mfr/extensions/audio/render.py
index 00b8be3fd..8bdd490bc 100644
--- a/mfr/extensions/audio/render.py
+++ b/mfr/extensions/audio/render.py
@@ -13,7 +13,7 @@ class AudioRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
safe_url = escape_url_for_template(self.url)
return self.TEMPLATE.render(base=self.assets_url, url=safe_url)
diff --git a/mfr/extensions/codepygments/exceptions.py b/mfr/extensions/codepygments/exceptions.py
index 9dbd53082..8b7581faf 100644
--- a/mfr/extensions/codepygments/exceptions.py
+++ b/mfr/extensions/codepygments/exceptions.py
@@ -13,7 +13,7 @@ class FileTooLargeError(CodePygmentsRendererError):
__TYPE = 'codepygments_file_too_large'
- def __init__(self, message, *args, code: int=400, file_size: int=None, max_size: int=None,
+ def __init__(self, message, *args, code: int = 400, file_size: int = None, max_size: int = None,
**kwargs):
super().__init__(message, *args, code=code, **kwargs)
@@ -33,8 +33,8 @@ class FileDecodingError(CodePygmentsRendererError):
__TYPE = 'codepygments_file_decoding'
- def __init__(self, message, *args, code: int=400, original_exception: Exception=None,
- category: str='', **kwargs):
+ def __init__(self, message, *args, code: int = 400, original_exception: Exception = None,
+ category: str = '', **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.category = category
diff --git a/mfr/extensions/codepygments/render.py b/mfr/extensions/codepygments/render.py
index a76b30ae2..89dc364dc 100644
--- a/mfr/extensions/codepygments/render.py
+++ b/mfr/extensions/codepygments/render.py
@@ -30,7 +30,7 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.metrics.add('pygments_version', pygments.__version__)
- def render(self):
+ def _render(self):
file_size = os.path.getsize(self.file_path)
if file_size > settings.MAX_SIZE:
raise exceptions.FileTooLargeError(
@@ -80,7 +80,7 @@ def _render_html(self, fp, ext, *args, **kwargs):
content = data.decode(encoding)
except UnicodeDecodeError as err:
raise exceptions.FileDecodingError(
- message='Unable to decode file as {}.'.format(encoding),
+ message=f'Unable to decode file as {encoding}.',
extension=ext,
category='undecodable',
original_exception=err,
@@ -89,7 +89,7 @@ def _render_html(self, fp, ext, *args, **kwargs):
if content is None:
raise exceptions.FileDecodingError(
- message='File decoded to undefined using encoding "{}"'.format(encoding),
+ message=f'File decoded to undefined using encoding "{encoding}"',
extension=ext,
category='decoded_to_undefined',
code=500,
diff --git a/mfr/extensions/docx/__init__.py b/mfr/extensions/docx/__init__.py
deleted file mode 100644
index 0cfb92575..000000000
--- a/mfr/extensions/docx/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .render import DocxRenderer # noqa
diff --git a/mfr/extensions/docx/render.py b/mfr/extensions/docx/render.py
deleted file mode 100644
index b5f24dd97..000000000
--- a/mfr/extensions/docx/render.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import os
-
-import pydocx.export
-from mako.lookup import TemplateLookup
-
-from mfr.core import extension
-
-
-class DocxRenderer(extension.BaseRenderer):
-
- TEMPLATE = TemplateLookup(
- directories=[
- os.path.join(os.path.dirname(__file__), 'templates')
- ]).get_template('viewer.mako')
-
- # Workaround to remove default stylesheet and inlined styles
- # see: https://github.com/CenterForOpenScience/pydocx/issues/102
- class _PyDocXHTMLExporter(pydocx.export.PyDocXHTMLExporter):
-
- def style(self):
- return ''
-
- def indent(self, text, *args, **kwargs):
- return text
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.metrics.add('pydocx_version', pydocx.__version__)
-
- def render(self):
- body = self._PyDocXHTMLExporter(self.file_path).parsed
- return self.TEMPLATE.render(base=self.assets_url, body=body)
-
- @property
- def file_required(self):
- return True
-
- @property
- def cache_result(self):
- return True
diff --git a/mfr/extensions/docx/templates/viewer.mako b/mfr/extensions/docx/templates/viewer.mako
deleted file mode 100644
index 36d6ac0ec..000000000
--- a/mfr/extensions/docx/templates/viewer.mako
+++ /dev/null
@@ -1,6 +0,0 @@
-
-${body}
-
-
-
-
diff --git a/mfr/extensions/image/exceptions.py b/mfr/extensions/image/exceptions.py
index 5780efb69..642d217bc 100644
--- a/mfr/extensions/image/exceptions.py
+++ b/mfr/extensions/image/exceptions.py
@@ -8,8 +8,8 @@ class PillowImageError(ExporterError):
__TYPE = 'image_pillow'
- def __init__(self, message, *args, export_format: str='', detected_format: str='',
- original_exception: Exception=None, **kwargs):
+ def __init__(self, message, *args, export_format: str = '', detected_format: str = '',
+ original_exception: Exception = None, **kwargs):
super().__init__(message, *args, exporter_class='image', **kwargs)
self.export_format = export_format
diff --git a/mfr/extensions/image/export.py b/mfr/extensions/image/export.py
index f95d7b8cb..23a22409a 100644
--- a/mfr/extensions/image/export.py
+++ b/mfr/extensions/image/export.py
@@ -1,5 +1,4 @@
import os
-import imghdr
import warnings
from PIL import Image
@@ -14,14 +13,14 @@ class ImageExporter(extension.BaseExporter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self.metrics.add('pil_version', Image.VERSION)
+ self.metrics.add('pil_version', Image.__version__)
def export(self):
parts = self.format.split('.')
image_type = parts[-1].lower()
max_size = {'w': None, 'h': None}
if len(parts) == 2:
- max_size['w'], max_size['h'] = [int(size) for size in parts[0].split('x')]
+ max_size['w'], max_size['h'] = (int(size) for size in parts[0].split('x'))
self.metrics.merge({
'type': image_type,
'max_size_w': max_size['w'],
@@ -45,7 +44,7 @@ def export(self):
self.metrics.add('ratio', ratio)
if ratio < 1:
size_tuple = (round(image.size[0] * ratio), round(image.size[1] * ratio))
- image = image.resize(size_tuple, Image.ANTIALIAS)
+ image = image.resize(size_tuple, Image.Resampling.LANCZOS)
# Mode 'P' is for paletted images. They must be converted to RGB before exporting to
# jpeg, otherwise Pillow will throw an error. This is a temporary workaround, as the
@@ -66,13 +65,20 @@ def export(self):
image.save(self.output_file_path, image_type)
image.close()
- except (UnicodeDecodeError, IOError, FileNotFoundError, OSError) as err:
+ except (UnicodeDecodeError, OSError, FileNotFoundError) as err:
os.path.splitext(os.path.split(self.source_file_path)[-1])
raise exceptions.PillowImageError(
'Unable to export the file as a {}, please check that the '
'file is a valid image.'.format(image_type),
export_format=image_type,
- detected_format=imghdr.what(self.source_file_path),
+ detected_format=self.detect_image_format(),
original_exception=err,
code=400,
)
+
+ def detect_image_format(self):
+ try:
+ with Image.open(self.source_file_path) as img:
+ return img.format.lower()
+ except Exception:
+ return None
diff --git a/mfr/extensions/image/render.py b/mfr/extensions/image/render.py
index 473d11dcd..827a1aef0 100644
--- a/mfr/extensions/image/render.py
+++ b/mfr/extensions/image/render.py
@@ -15,7 +15,7 @@ class ImageRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
self.metrics.add('needs_export', False)
if self.metadata.ext in settings.EXPORT_EXCLUSIONS:
download_url = munge_url_for_localdev(self.url)
@@ -24,7 +24,7 @@ def render(self):
exported_url = furl.furl(self.export_url)
if settings.EXPORT_MAXIMUM_SIZE and settings.EXPORT_TYPE:
- exported_url.args['format'] = '{}.{}'.format(settings.EXPORT_MAXIMUM_SIZE, settings.EXPORT_TYPE)
+ exported_url.args['format'] = f'{settings.EXPORT_MAXIMUM_SIZE}.{settings.EXPORT_TYPE}'
elif settings.EXPORT_TYPE:
exported_url.args['format'] = settings.EXPORT_TYPE
else:
diff --git a/mfr/extensions/ipynb/exceptions.py b/mfr/extensions/ipynb/exceptions.py
index c7e41456a..1f3759032 100644
--- a/mfr/extensions/ipynb/exceptions.py
+++ b/mfr/extensions/ipynb/exceptions.py
@@ -5,8 +5,8 @@ class InvalidFormatError(RendererError):
__TYPE = 'ipynb_invalid_format'
- def __init__(self, message, *args, code: int=400, download_url: str='',
- original_exception: Exception=None, **kwargs):
+ def __init__(self, message, *args, code: int = 400, download_url: str = '',
+ original_exception: Exception = None, **kwargs):
super().__init__(message, *args, code=code, renderer_class='ipynb', **kwargs)
self.download_url = download_url,
diff --git a/mfr/extensions/ipynb/render.py b/mfr/extensions/ipynb/render.py
index c93232b3f..c4fcc8d82 100644
--- a/mfr/extensions/ipynb/render.py
+++ b/mfr/extensions/ipynb/render.py
@@ -22,13 +22,13 @@ def __init__(self, *args, **kwargs):
self.metrics.add('nbformat_version', nbformat.__version__)
self.metrics.add('nbconvert_version', nbconvert.__version__)
- def render(self):
+ def _render(self):
try:
- with open(self.file_path, 'r') as file_pointer:
+ with open(self.file_path) as file_pointer:
notebook = nbformat.reads(file_pointer.read(), as_version=4)
except ValueError as err:
raise exceptions.InvalidFormatError(
- 'Could not read ipython notebook file. {}'.format(str(err)),
+ f'Could not read ipython notebook file. {str(err)}',
extension=self.metadata.ext,
download_url=str(self.metadata.download_url),
original_exception=err,
@@ -36,7 +36,7 @@ def render(self):
exporter = HTMLExporter(config=Config({
'HTMLExporter': {
- 'template_file': 'basic',
+ 'template_name': 'basic',
},
'CSSHtmlHeaderTransformer': {
'enabled': False,
diff --git a/mfr/extensions/jamovi/exceptions.py b/mfr/extensions/jamovi/exceptions.py
index e1744d3c3..9a4ce4d4e 100644
--- a/mfr/extensions/jamovi/exceptions.py
+++ b/mfr/extensions/jamovi/exceptions.py
@@ -14,8 +14,8 @@ class JamoviVersionError(JamoviRendererError):
__TYPE = 'jamovi_version'
- def __init__(self, message, *args, code: int=400, created_by: str='',
- actual_version: str='', required_version: str='', **kwargs):
+ def __init__(self, message, *args, code: int = 400, created_by: str = '',
+ actual_version: str = '', required_version: str = '', **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.created_by = created_by
self.actual_version = actual_version
@@ -34,8 +34,8 @@ class JamoviFileCorruptError(JamoviRendererError):
__TYPE = 'jamovi_file_corrupt'
- def __init__(self, message, *args, code: int=400, corruption_type: str='',
- reason: str='', **kwargs):
+ def __init__(self, message, *args, code: int = 400, corruption_type: str = '',
+ reason: str = '', **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.corruption_type = corruption_type
self.reason = reason
diff --git a/mfr/extensions/jamovi/render.py b/mfr/extensions/jamovi/render.py
index 8e59a6052..59c241e48 100644
--- a/mfr/extensions/jamovi/render.py
+++ b/mfr/extensions/jamovi/render.py
@@ -22,7 +22,7 @@ class JamoviRenderer(extension.BaseRenderer):
MESSAGE_FILE_CORRUPT = 'This jamovi file is corrupt and cannot be viewed.'
MESSAGE_NO_PREVIEW = 'This jamovi file does not support previews.'
- def render(self):
+ def _render(self):
try:
with ZipFile(self.file_path) as zip_file:
self._check_file(zip_file)
@@ -30,7 +30,7 @@ def render(self):
return self.TEMPLATE.render(base=self.assets_url, body=body)
except BadZipFile as err:
raise jamovi_exceptions.JamoviRendererError(
- '{} {}.'.format(self.MESSAGE_FILE_CORRUPT, str(err)),
+ f'{self.MESSAGE_FILE_CORRUPT} {str(err)}.',
extension=self.metadata.ext,
corruption_type='bad_zip',
reason=str(err),
@@ -76,7 +76,7 @@ def _check_file(self, zip_file):
manifest = manifest_data.read().decode('utf-8')
except KeyError:
raise jamovi_exceptions.JamoviFileCorruptError(
- '{} Missing manifest'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} Missing manifest',
extension=self.metadata.ext,
corruption_type='key_error',
reason='zip missing manifest',
@@ -93,7 +93,7 @@ def _check_file(self, zip_file):
break
else:
raise jamovi_exceptions.JamoviFileCorruptError(
- '{} Data-Archive-Version not found.'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} Data-Archive-Version not found.',
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
reason='Data-Archive-Version not found.',
@@ -104,17 +104,17 @@ def _check_file(self, zip_file):
try:
if archive_version < self.MINIMUM_VERSION:
raise jamovi_exceptions.JamoviFileCorruptError(
- '{} Data-Archive-Version is too old.'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} Data-Archive-Version is too old.',
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
reason='Data-Archive-Version not found.',
)
except TypeError:
raise jamovi_exceptions.JamoviFileCorruptError(
- '{} Data-Archive-Version not parsable.'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} Data-Archive-Version not parsable.',
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
- reason='Data-Archive-Version ({}) not parsable.'.format(version_str),
+ reason=f'Data-Archive-Version ({version_str}) not parsable.',
)
return True
diff --git a/mfr/extensions/jasp/exceptions.py b/mfr/extensions/jasp/exceptions.py
index 438b7ec0b..8573f176d 100644
--- a/mfr/extensions/jasp/exceptions.py
+++ b/mfr/extensions/jasp/exceptions.py
@@ -14,8 +14,8 @@ class JaspVersionError(JaspRendererError):
__TYPE = 'jasp_version'
- def __init__(self, message, *args, code: int=400, created_by: str='',
- actual_version: str='', required_version: str='', **kwargs):
+ def __init__(self, message, *args, code: int = 400, created_by: str = '',
+ actual_version: str = '', required_version: str = '', **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.created_by = created_by
self.actual_version = actual_version
@@ -34,8 +34,8 @@ class JaspFileCorruptError(JaspRendererError):
__TYPE = 'jasp_file_corrupt'
- def __init__(self, message, *args, code: int=400, corruption_type: str='',
- reason: str='', **kwargs):
+ def __init__(self, message, *args, code: int = 400, corruption_type: str = '',
+ reason: str = '', **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.corruption_type = corruption_type
self.reason = reason
diff --git a/mfr/extensions/jasp/html_processor.py b/mfr/extensions/jasp/html_processor.py
index 1dbf4547f..26289cb2f 100644
--- a/mfr/extensions/jasp/html_processor.py
+++ b/mfr/extensions/jasp/html_processor.py
@@ -1,4 +1,3 @@
-
from io import StringIO
from html.parser import HTMLParser
diff --git a/mfr/extensions/jasp/render.py b/mfr/extensions/jasp/render.py
index abcece4b4..ae2b2bf8f 100644
--- a/mfr/extensions/jasp/render.py
+++ b/mfr/extensions/jasp/render.py
@@ -21,7 +21,7 @@ class JASPRenderer(extension.BaseRenderer):
MESSAGE_FILE_CORRUPT = 'This JASP file is corrupt and cannot be viewed.'
- def render(self):
+ def _render(self):
try:
with ZipFile(self.file_path) as zip_file:
self._check_file(zip_file)
@@ -29,7 +29,7 @@ def render(self):
return self.TEMPLATE.render(base=self.assets_url, body=body)
except BadZipFile as err:
raise exceptions.JaspFileCorruptError(
- '{} Failure to unzip. {}.'.format(self.MESSAGE_FILE_CORRUPT, str(err)),
+ f'{self.MESSAGE_FILE_CORRUPT} Failure to unzip. {str(err)}.',
extension=self.metadata.ext,
corruption_type='bad_zip',
reason=str(err),
@@ -50,7 +50,7 @@ def _render_html(self, zip_file, ext, *args, **kwargs):
index = index_data.read().decode('utf-8')
except KeyError:
raise exceptions.JaspFileCorruptError(
- '{} Missing index.html.'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} Missing index.html.',
extension=self.metadata.ext,
corruption_type='key_error',
reason='zip missing ./index.html',
@@ -78,7 +78,7 @@ def _check_file(self, zip_file):
manifest, flavor = manifest_data.read().decode('utf-8'), 'java'
except KeyError:
raise exceptions.JaspFileCorruptError(
- '{} Missing manifest'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} Missing manifest',
extension=self.metadata.ext,
corruption_type='key_error',
reason='zip missing manifest',
@@ -107,7 +107,7 @@ def _verify_java_manifest(self, manifest):
createdBy = str(value)
if not dataArchiveVersionStr:
raise exceptions.JaspFileCorruptError(
- '{} Data-Archive-Version not found.'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} Data-Archive-Version not found.',
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
reason='Data-Archive-Version not found.',
@@ -130,10 +130,10 @@ def _verify_java_manifest(self, manifest):
)
except TypeError:
raise exceptions.JaspFileCorruptError(
- '{} Data-Archive-Version not parsable.'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} Data-Archive-Version not parsable.',
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
- reason='Data-Archive-Version ({}) not parsable.'.format(dataArchiveVersionStr),
+ reason=f'Data-Archive-Version ({dataArchiveVersionStr}) not parsable.',
)
return
@@ -145,7 +145,7 @@ def _verify_json_manifest(self, manifest):
jasp_archive_version_str = manifest_data.get('jaspArchiveVersion', None)
if not jasp_archive_version_str:
raise exceptions.JaspFileCorruptError(
- '{} jaspArchiveVersion not found.'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} jaspArchiveVersion not found.',
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
reason='jaspArchiveVersion not found.',
@@ -167,10 +167,10 @@ def _verify_json_manifest(self, manifest):
)
except TypeError:
raise exceptions.JaspFileCorruptError(
- '{} jaspArchiveVersion not parsable.'.format(self.MESSAGE_FILE_CORRUPT),
+ f'{self.MESSAGE_FILE_CORRUPT} jaspArchiveVersion not parsable.',
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
- reason='jaspArchiveVersion ({}) not parsable.'.format(jasp_archive_version_str),
+ reason=f'jaspArchiveVersion ({jasp_archive_version_str}) not parsable.',
)
return
diff --git a/mfr/extensions/jsc3d/freecad_converter.py b/mfr/extensions/jsc3d/freecad_converter.py
index 45b26bfc6..095651fda 100644
--- a/mfr/extensions/jsc3d/freecad_converter.py
+++ b/mfr/extensions/jsc3d/freecad_converter.py
@@ -11,7 +11,8 @@
try:
Part.open(in_fn)
-except:
+except Exception:
+ # Todo: maybe it is needed to use logger and specific message for exception logging
sys.exit(1)
o = [FreeCAD.getDocument("Unnamed").findObjects()[0]]
diff --git a/mfr/extensions/jsc3d/render.py b/mfr/extensions/jsc3d/render.py
index 3bff7b024..2a9dd858b 100644
--- a/mfr/extensions/jsc3d/render.py
+++ b/mfr/extensions/jsc3d/render.py
@@ -17,7 +17,7 @@ class JSC3DRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
self.metrics.add('needs_export', False)
if self.metadata.ext in settings.EXPORT_EXCLUSIONS:
download_url = munge_url_for_localdev(self.metadata.download_url)
diff --git a/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js b/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js
index 117a33f69..539e05009 100644
--- a/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js
+++ b/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js
@@ -77,11 +77,13 @@ JSC3D.Autodesk3DSLoader.prototype.loadFromUrl = function(urlName) {
xhr.onreadystatechange = function() {
if(this.readyState == 4) {
if(this.status == 200 || this.status == 0) {
- if(JSC3D.console)
+ if(JSC3D.console) {
JSC3D.console.logInfo('Finished loading 3DS file "' + urlName + '".');
+ }
if(self.onload) {
- if(self.onprogress)
+ if(self.onprogress) {
self.onprogress('Loading 3DS file ...', 1);
+ }
// if(JSC3D.PlatformInfo.browser == 'ie' && JSC3D.PlatformInfo.version >= '10') {
// // asynchronously decode blob to binary string
// var blobReader = new FileReader;
@@ -107,10 +109,12 @@ JSC3D.Autodesk3DSLoader.prototype.loadFromUrl = function(urlName) {
}
}
else {
- if(JSC3D.console)
+ if(JSC3D.console) {
JSC3D.console.logError('Failed to load 3DS file "' + urlName + '".');
- if(self.onerror)
+ }
+ if(self.onerror) {
self.onerror('Failed to load 3DS file "' + urlName + '".');
+ }
}
self.request = null;
}
@@ -199,9 +203,12 @@ JSC3D.Autodesk3DSLoader.prototype.readAmount = function(reader,end) {
len = reader.readUInt32();
switch (cid) {
- case 0x0030: // Floats
+ case 0x0030:
amount = reader.readUInt16();
break;
+ case 0x0031:
+ amount = reader.readFloat32() * 100.0;
+ break;
default:
break;
}
@@ -461,14 +468,16 @@ JSC3D.Autodesk3DSLoader.prototype.parseObjectAnimation = function (reader,end) {
if (name != '$$$DUMMY' && this._unfinalized_objects.hasOwnProperty(name)) {
vo = this._unfinalized_objects[name];
// todo vasea
- if(JSC3D.console)
+ if(JSC3D.console) {
JSC3D.console.logInfo('Construct object '+vo.name);
+ }
// this._cur_obj = null;
obj = null;//this.constructObject(vo, pivot);
if (obj) {
- if(JSC3D.console)
+ if(JSC3D.console) {
JSC3D.console.logInfo('finished loading the object '+vo.name);
+ }
}
delete this._unfinalized_objects[name];
@@ -489,8 +498,8 @@ JSC3D.Autodesk3DSLoader.prototype.parseSmoothingGroups = function (reader) {
JSC3D.Autodesk3DSLoader.prototype.finalizeCurrentMaterial = function () {
var mat = new JSC3D.Material;
- if (this._cur_mat.colorMap) {
- mat.textureFileName = this._cur_mat.colorMap.texture;
+ if (this._cur_mat.colorMap && this._cur_mat.colorMap.url) {
+ mat.textureFileName = this._cur_mat.colorMap.url;
}
else {
mat.diffuseColor = this._cur_mat.diffuseColor;
@@ -517,8 +526,9 @@ JSC3D.Autodesk3DSLoader.prototype.setupTexture = function(meshList, textureUrlNa
texture.onready = function() {
for(var i=0; i0);
- mesh.isDoubleSided = true;//currentMaterial.twoSided;
- mesh.material.transparency = currentMaterial.transparency>0?(currentMaterial.transparency)/100:0;
+
+ // Transparency: normalize (0..1), snap tiny values to 0 to avoid z-sort artifacts
+ var t = currentMaterial.transparency;
+ if (typeof t === 'number') {
+ var alpha = (t > 1) ? (t / 100.0) : t;
+ alpha = Math.max(0, Math.min(1, alpha));
+ if (alpha < 0.01) alpha = 0;
+ mesh.material.transparency = alpha;
+ } else {
+ mesh.material.transparency = 0;
+ }
+
+ var two = (currentMaterial.twoSided !== undefined) ? !!currentMaterial.twoSided : true;
+ mesh.isDoubleSided = two;
+ mesh.material.bothSides = two;
}
+ if (!sawMaterial) {
+ mesh.isDoubleSided = true;
+ mesh.material.bothSides = true;
+ mesh.material.transparency = 0;
+ }
+ if (!mesh.texCoordBuffer || !mesh.texCoordIndexBuffer) {
+ mesh.texCoordBuffer = null;
+ mesh.texCoordIndexBuffer = null;
+ }
//mesh.faceNormalBuffer = [];
// mesh.init();
@@ -672,7 +721,7 @@ JSC3D.Autodesk3DSLoader.prototype.parse3DS = function(scene, data) {
this._cur_obj = {};
this._cur_obj.name = this.readNulTermString(reader);
this._cur_obj.materials = [];
- this._cur_obj.materialFaces = [];
+ this._cur_obj.materialFaces = {};
break;
case 0x4100: // OBJ_TRIMESH
diff --git a/mfr/extensions/md/render.py b/mfr/extensions/md/render.py
index 792f07256..11a1b1e49 100644
--- a/mfr/extensions/md/render.py
+++ b/mfr/extensions/md/render.py
@@ -9,9 +9,9 @@
class EscapeHtml(Extension):
- def extendMarkdown(self, md, md_globals):
- del md.preprocessors['html_block']
- del md.inlinePatterns['html']
+ def extendMarkdown(self, md):
+ md.preprocessors.deregister('html_block')
+ md.inlinePatterns.deregister('html')
class MdRenderer(extension.BaseRenderer):
@@ -23,11 +23,11 @@ class MdRenderer(extension.BaseRenderer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self.metrics.add('markdown_version', markdown.version)
+ self.metrics.add('markdown_version', markdown.__version__)
- def render(self):
+ def _render(self):
"""Render a markdown file to html."""
- with open(self.file_path, 'r') as fp:
+ with open(self.file_path) as fp:
body = markdown.markdown(fp.read(), extensions=[EscapeHtml()])
return self.TEMPLATE.render(base=self.assets_url, body=body)
diff --git a/mfr/extensions/pdb/render.py b/mfr/extensions/pdb/render.py
index 41d88da58..b779cb2a5 100644
--- a/mfr/extensions/pdb/render.py
+++ b/mfr/extensions/pdb/render.py
@@ -16,7 +16,7 @@ class PdbRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
download_url = munge_url_for_localdev(self.metadata.download_url)
safe_url = escape_url_for_template(download_url.geturl())
return self.TEMPLATE.render(
diff --git a/mfr/extensions/pdf/exceptions.py b/mfr/extensions/pdf/exceptions.py
index cb227aaed..73bf34185 100644
--- a/mfr/extensions/pdf/exceptions.py
+++ b/mfr/extensions/pdf/exceptions.py
@@ -8,8 +8,8 @@ class PillowImageError(ExporterError):
__TYPE = 'pdf_pillow'
- def __init__(self, message, *args, export_format: str='', detected_format: str='',
- original_exception: Exception=None, **kwargs):
+ def __init__(self, message, *args, export_format: str = '', detected_format: str = '',
+ original_exception: Exception = None, **kwargs):
super().__init__(message, *args, exporter_class='image', **kwargs)
self.export_format = export_format
diff --git a/mfr/extensions/pdf/export.py b/mfr/extensions/pdf/export.py
index 18f7a7f12..ca6be994d 100644
--- a/mfr/extensions/pdf/export.py
+++ b/mfr/extensions/pdf/export.py
@@ -1,5 +1,3 @@
-import os
-import imghdr
import logging
from http import HTTPStatus
@@ -18,7 +16,7 @@ class PdfExporter(extension.BaseExporter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self.metrics.add('pil_version', Image.VERSION)
+ self.metrics.add('pil_version', Image.__version__)
def tiff_to_pdf(self, tiff_img, max_size):
""" Turn a tiff into a pdf to support multipage tiffs"""
@@ -66,7 +64,7 @@ def tiff_to_pdf(self, tiff_img, max_size):
c.save()
def export(self):
- logger.debug('pdf-export: format::{}'.format(self.format))
+ logger.debug(f'pdf-export: format::{self.format}')
parts = self.format.split('.')
export_type = parts[-1].lower()
max_size = [int(x) for x in parts[0].split('x')] if len(parts) == 2 else None
@@ -89,13 +87,19 @@ def export(self):
self.tiff_to_pdf(image, max_size)
image.close()
- except (UnicodeDecodeError, IOError) as err:
- name, extension = os.path.splitext(os.path.split(self.source_file_path)[-1])
+ except (UnicodeDecodeError, OSError) as err:
raise exceptions.PillowImageError(
'Unable to export the file as a {}, please check that the '
'file is a valid tiff image.'.format(export_type),
export_format=export_type,
- detected_format=imghdr.what(self.source_file_path),
+ detected_format=self.detect_image_format(),
original_exception=err,
code=HTTPStatus.BAD_REQUEST,
)
+
+ def detect_image_format(self):
+ try:
+ with Image.open(self.source_file_path) as img:
+ return img.format.lower()
+ except Exception:
+ return None
diff --git a/mfr/extensions/pdf/render.py b/mfr/extensions/pdf/render.py
index 147d0cab4..5d305b23d 100644
--- a/mfr/extensions/pdf/render.py
+++ b/mfr/extensions/pdf/render.py
@@ -19,11 +19,11 @@ class PdfRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
download_url = munge_url_for_localdev(self.metadata.download_url)
escaped_name = escape_url_for_template(
- '{}{}'.format(self.metadata.name, self.metadata.ext)
+ f'{self.metadata.name}{self.metadata.ext}'
)
logger.debug('extension::{} supported-list::{}'.format(self.metadata.ext,
settings.EXPORT_SUPPORTED))
diff --git a/mfr/extensions/rst/render.py b/mfr/extensions/rst/render.py
index fd853814f..115218b61 100644
--- a/mfr/extensions/rst/render.py
+++ b/mfr/extensions/rst/render.py
@@ -19,8 +19,8 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.metrics.add('docutils_version', docutils.__version__)
- def render(self):
- with open(self.file_path, 'r') as fp:
+ def _render(self):
+ with open(self.file_path) as fp:
body = publish_parts(fp.read(), writer_name='html')['html_body']
return self.TEMPLATE.render(base=self.assets_url, body=body)
diff --git a/mfr/extensions/svg/render.py b/mfr/extensions/svg/render.py
index ca0293107..9565240ac 100644
--- a/mfr/extensions/svg/render.py
+++ b/mfr/extensions/svg/render.py
@@ -14,7 +14,7 @@ class SvgRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
safe_url = escape_url_for_template(self.url)
return self.TEMPLATE.render(base=self.assets_url, url=safe_url)
diff --git a/mfr/extensions/tabular/compat.py b/mfr/extensions/tabular/compat.py
index e4bca09ac..4bb6a1988 100644
--- a/mfr/extensions/tabular/compat.py
+++ b/mfr/extensions/tabular/compat.py
@@ -1,5 +1,3 @@
-from __future__ import division
-
range = range
string_types = (str,)
unicode = str
diff --git a/mfr/extensions/tabular/exceptions.py b/mfr/extensions/tabular/exceptions.py
index 59f461eb6..75b3103c8 100644
--- a/mfr/extensions/tabular/exceptions.py
+++ b/mfr/extensions/tabular/exceptions.py
@@ -10,7 +10,7 @@ class MissingRequirementsError(TabularRendererError):
__TYPE = 'tabular_missing_requirements'
- def __init__(self, message, *args, code: int=500, function_preference: str='', **kwargs):
+ def __init__(self, message, *args, code: int = 500, function_preference: str = '', **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.function_preference = function_preference
self.attr_stack.append([self.__TYPE, {'function_preference': self.function_preference}])
@@ -20,7 +20,7 @@ class EmptyTableError(TabularRendererError):
__TYPE = 'tabular_empty_table'
- def __init__(self, message, *args, code: int=400, **kwargs):
+ def __init__(self, message, *args, code: int = 400, **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.attr_stack.append([self.__TYPE, {}])
@@ -29,7 +29,7 @@ class TableTooBigError(TabularRendererError):
__TYPE = 'tabular_table_too_big'
- def __init__(self, message, *args, code: int=400, nbr_cols: int=0, nbr_rows: int=0, **kwargs):
+ def __init__(self, message, *args, code: int = 400, nbr_cols: int = 0, nbr_rows: int = 0, **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.nbr_cols = nbr_cols
self.nbr_rows = nbr_rows
@@ -43,7 +43,7 @@ class UnexpectedFormattingError(TabularRendererError):
__TYPE = 'tabular_unexpected_formatting'
- def __init__(self, message, *args, code: int=500, formatting_function: str='', **kwargs):
+ def __init__(self, message, *args, code: int = 500, formatting_function: str = '', **kwargs):
super().__init__(message, *args, code=code, **kwargs)
self.formatting_function = formatting_function
self.attr_stack.append([self.__TYPE, {'formatting_function': self.formatting_function}])
@@ -53,7 +53,7 @@ class FileTooLargeError(TabularRendererError):
__TYPE = 'tabular_file_too_large'
- def __init__(self, message, *args, code: int=400, file_size: int=None, max_size: int=None,
+ def __init__(self, message, *args, code: int = 400, file_size: int = None, max_size: int = None,
**kwargs):
super().__init__(message, *args, code=code, **kwargs)
diff --git a/mfr/extensions/tabular/libs/__init__.py b/mfr/extensions/tabular/libs/__init__.py
index 836e9bda0..a79ec321b 100644
--- a/mfr/extensions/tabular/libs/__init__.py
+++ b/mfr/extensions/tabular/libs/__init__.py
@@ -31,10 +31,14 @@ def sav_pandas():
from ..libs.panda_tools import sav_pandas
return sav_pandas
+def xls():
+ from ..libs.xlrd_tools import xls
+ return xls
-def xlsx_xlrd():
- from ..libs.xlrd_tools import xlsx_xlrd
- return xlsx_xlrd
+
+def xlsx():
+ from ..libs.xlrd_tools import xlsx
+ return xlsx
def mat_h5py_scipy():
from ..libs.h5py_scipy_tools import mat_h5py_scipy
diff --git a/mfr/extensions/tabular/libs/h5py_scipy_tools.py b/mfr/extensions/tabular/libs/h5py_scipy_tools.py
index 4e6bcf4c2..1090d038b 100644
--- a/mfr/extensions/tabular/libs/h5py_scipy_tools.py
+++ b/mfr/extensions/tabular/libs/h5py_scipy_tools.py
@@ -31,7 +31,7 @@ def mat_v73(fp):
if isinstance(data, h5py.Dataset):
# h5py Uses row-major ordering. this fixes it so it displays like it does in matlab
# basically just flip it on its axis
- list_data = list(zip(*data.value.tolist()))
+ list_data = list(zip(*data[()].tolist()))
build_sheets(name, list_data, sheets)
return sheets
diff --git a/mfr/extensions/tabular/libs/panda_tools.py b/mfr/extensions/tabular/libs/panda_tools.py
index 69810245a..fbdfd4f2c 100644
--- a/mfr/extensions/tabular/libs/panda_tools.py
+++ b/mfr/extensions/tabular/libs/panda_tools.py
@@ -51,7 +51,7 @@ def sav_pandas(fp):
def data_from_dataframe(dataframe):
"""Convert a dataframe object to a list of dictionaries
- :param fp: File pointer object
+ :param dataframe: pandas dataframe
:return: tuple of table headers and data
"""
@@ -62,9 +62,9 @@ def data_from_dataframe(dataframe):
data = []
for _, frame_row in dataframe.iterrows():
data_row = {}
- for name, value in frame_row.iteritems():
+ for name, value in frame_row.items():
try:
- data_row[name] = numpy.asscalar(value)
+ data_row[name] = value.item()
except AttributeError:
data_row[name] = value
data.append(data_row)
diff --git a/mfr/extensions/tabular/libs/stdlib_tools.py b/mfr/extensions/tabular/libs/stdlib_tools.py
index 3d3611984..541154cb6 100644
--- a/mfr/extensions/tabular/libs/stdlib_tools.py
+++ b/mfr/extensions/tabular/libs/stdlib_tools.py
@@ -27,7 +27,7 @@ def csv_stdlib(fp):
for idx, fieldname in enumerate(reader.fieldnames or []):
column_count = sum(1 for column in columns if fieldname == column['name'])
if column_count:
- unique_fieldname = '{}-{}'.format(fieldname, column_count + 1)
+ unique_fieldname = f'{fieldname}-{column_count + 1}'
reader.fieldnames[idx] = unique_fieldname
else:
unique_fieldname = fieldname
@@ -49,7 +49,7 @@ def csv_stdlib(fp):
extension='csv',
) from e
else:
- raise TabularRendererError('csv.Error: {}'.format(e), extension='csv') from e
+ raise TabularRendererError(f'csv.Error: {e}', extension='csv') from e
if not columns and not rows:
raise EmptyTableError('Table empty or corrupt.', extension='csv')
@@ -66,7 +66,7 @@ def sav_stdlib(fp):
:return: tuple of table headers and data
"""
csv_file = utilities.sav_to_csv(fp)
- with open(csv_file.name, 'r') as file:
+ with open(csv_file.name) as file:
csv_file.close()
return csv_stdlib(file)
@@ -83,12 +83,12 @@ def _set_dialect_quote_attrs(dialect, data):
'{"a", "b", "c" for quotechar == "
"""
if dialect.quotechar == '"':
- if re.search('\'[[({]".+",', data):
+ if re.search('\'[([{]".+",', data):
dialect.quotechar = "'"
- if re.search("'''[[({]\".+\",", data):
+ if re.search("'''[([{]\".+\",", data):
dialect.doublequote = True
elif dialect.quotechar == "'":
- if re.search("\"[[({]'.+',", data):
+ if re.search("\"[([{]'.+',", data):
dialect.quotechar = '"'
- if re.search('"""[[({]\'.+\',', data):
+ if re.search('"""[([{]\'.+\',', data):
dialect.doublequote = True
diff --git a/mfr/extensions/tabular/libs/xlrd_tools.py b/mfr/extensions/tabular/libs/xlrd_tools.py
index 7afbd145d..817d7932d 100644
--- a/mfr/extensions/tabular/libs/xlrd_tools.py
+++ b/mfr/extensions/tabular/libs/xlrd_tools.py
@@ -1,52 +1,34 @@
import xlrd
-from collections import OrderedDict
-from ..exceptions import TableTooBigError
+import zipfile
-from ..utilities import header_population
-from mfr.extensions.tabular.compat import range, basestring
+from io import BytesIO
+from openpyxl import load_workbook
+from collections import OrderedDict
+from ..utilities import (
+ to_bytes,
+ parse_xls,
+ parse_xlsx
+)
-def xlsx_xlrd(fp):
- """Read and convert a xlsx file to JSON format using the xlrd library
- :param fp: File pointer object
- :return: tuple of table headers and data
+def xls(fp):
+ """
+ .xls → xlrd; supports truncation and optional meta collection.
"""
- max_size = 10000
-
- wb = xlrd.open_workbook(fp.name)
-
sheets = OrderedDict()
+ wb = xlrd.open_workbook(file_contents=to_bytes(fp))
+ return parse_xls(wb, sheets)
- for sheet in wb.sheets():
- if sheet.ncols > max_size or sheet.nrows > max_size:
- raise TableTooBigError('Table is too large to render.', '.xlsx',
- nbr_cols=sheet.ncols, nbr_rows=sheet.nrows)
-
- if sheet.ncols < 1 or sheet.nrows < 1:
- sheets[sheet.name] = ([], [])
- continue
-
- fields = sheet.row_values(0) if sheet.nrows else []
-
- fields = [
- str(value)
- if not isinstance(value, basestring) and value is not None
- else value or 'Unnamed: {0}'.format(index + 1)
- for index, value in enumerate(fields)
- ]
-
- data = []
- for i in range(1, sheet.nrows):
- row = []
- for cell in sheet.row(i):
- if cell.ctype == xlrd.XL_CELL_DATE:
- value = xlrd.xldate.xldate_as_datetime(cell.value, wb.datemode).isoformat()
- else:
- value = cell.value
- row.append(value)
- data.append(dict(zip(fields, row)))
-
- header = header_population(fields)
- sheets[sheet.name] = (header, data)
-
- return sheets
+def xlsx(fp):
+ """
+ .xlsx → openpyxl; supports truncation and optional meta collection.
+ """
+ sheets = OrderedDict()
+ try:
+ wb = load_workbook(BytesIO(to_bytes(fp)), data_only=True, read_only=True)
+ except zipfile.BadZipFile as exc:
+ raise xlrd.biffh.XLRDError(
+ "Invalid xlsx file or corrupted ZIP structure"
+ ) from exc
+
+ return parse_xlsx(wb, sheets)
diff --git a/mfr/extensions/tabular/render.py b/mfr/extensions/tabular/render.py
index 1c3ee539c..0f1e7168f 100644
--- a/mfr/extensions/tabular/render.py
+++ b/mfr/extensions/tabular/render.py
@@ -11,6 +11,7 @@
logger = logging.getLogger(__name__)
+BINARY_EXCEL_EXTS = {'.xls', '.xlsx'}
class TabularRenderer(extension.BaseRenderer):
@@ -19,7 +20,7 @@ class TabularRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
file_size = os.path.getsize(self.file_path)
if file_size > settings.MAX_FILE_SIZE:
raise exceptions.FileTooLargeError(
@@ -30,8 +31,14 @@ def render(self):
extension=self.metadata.ext,
)
- with open(self.file_path, errors='replace') as fp:
- sheets, size, nbr_rows, nbr_cols = self._render_grid(fp, self.metadata.ext)
+ ext = (self.metadata.ext or '').lower()
+ if ext in BINARY_EXCEL_EXTS:
+ open_kwargs = {'mode': 'rb'}
+ else:
+ open_kwargs = {'errors': 'replace'}
+
+ with open(self.file_path, **open_kwargs) as fp:
+ sheets, size, nbr_rows, nbr_cols = self._render_grid(fp, ext)
# Force GC
gc.collect()
@@ -43,6 +50,7 @@ def render(self):
height=settings.TABLE_HEIGHT,
sheets=json.dumps(sheets),
options=json.dumps(size),
+ max_size=settings.MAX_SIZE,
)
assert nbr_rows and nbr_cols
diff --git a/mfr/extensions/tabular/settings.py b/mfr/extensions/tabular/settings.py
index af6b9b0a2..5ca57afce 100644
--- a/mfr/extensions/tabular/settings.py
+++ b/mfr/extensions/tabular/settings.py
@@ -12,9 +12,9 @@
LIBS = config.get_object('LIBS', {
'.csv': [libs.csv_stdlib],
'.tsv': [libs.csv_stdlib],
- '.gsheet': [libs.xlsx_xlrd],
- '.xlsx': [libs.xlsx_xlrd],
- '.xls': [libs.xlsx_xlrd],
+ '.gsheet': [libs.xlsx],
+ '.xlsx': [libs.xlsx],
+ '.xls': [libs.xls],
'.dta': [libs.dta_pandas],
'.sav': [libs.sav_stdlib],
'.mat': [libs.mat_h5py_scipy],
diff --git a/mfr/extensions/tabular/templates/viewer.mako b/mfr/extensions/tabular/templates/viewer.mako
index a24e157fd..b41961d06 100644
--- a/mfr/extensions/tabular/templates/viewer.mako
+++ b/mfr/extensions/tabular/templates/viewer.mako
@@ -4,10 +4,11 @@
+
@@ -30,6 +31,19 @@
var grid;
var data;
var searchString = "";
+ var MAX_ROWS_LIMIT = ${max_size};
+
+ function refreshNotice() {
+ var $n = $("#mfr-tabular-notice");
+ if (!grid) { $n.hide().text(""); return; }
+ var rendered = grid.getDataLength ? grid.getDataLength() : (data ? data.length : 0);
+ if (rendered >= MAX_ROWS_LIMIT) {
+ $n.text("Table exceeds the max size limit — rendered first " + rendered + " rows.");
+ $n.show();
+ } else {
+ $n.hide().text("");
+ }
+ }
for (var sheetName in sheets){
var sheet = sheets[sheetName];
@@ -45,14 +59,16 @@
grid = new Slick.Grid('#mfrGrid', rows, columns, options);
searchString = "";
- $("#txtSearch").value = "";
+ $("#txtSearch").val("");
data = grid.getData();
grid.onSort.subscribe(sortData);
+ refreshNotice();
});
}
$("#tabular-tabs").tab();
$("#tabular-tabs a:first").click();
+ setTimeout(refreshNotice, 0);
$("#txtSearch").keyup(function (e) {
// clear on Esc
@@ -75,17 +91,21 @@
function filterData(data, search) {
var filteredData = [];
- var re = new RegExp(search, 'i');
- for (var i = 0; i
= MAX_SIZE:
+ break
+ rows.append(dict(zip(fields, row)))
+ return rows
+
+
+def parse_xls(wb, sheets):
+ for sheet in wb.sheets():
+ if getattr(sheet, 'nrows', None) is None or getattr(sheet, 'ncols', None) is None:
+ raise CorruptedError
+
+ ncols = sheet.ncols
+ max_cols = min(ncols, MAX_SIZE)
+ fields = fix_headers(sheet.row_values(0)[:max_cols])
+ raw_rows = (
+ row_vals(sheet.row(r)[:max_cols], wb.datemode)
+ for r in range(1, sheet.nrows)
+ )
+ rows = _extract_rows(fields, raw_rows)
+ sheets[sheet.name] = (header_population(fields), rows)
+ return sheets
+
+
+def parse_xlsx(wb, sheets):
+ for name in wb.sheetnames:
+ ws = wb[name]
+
+ if getattr(ws, 'max_row', None) is None or getattr(ws, 'max_column', None) is None:
+ raise CorruptedError
+
+ ncols = getattr(ws, "max_column", 0)
+ max_cols = min(ncols, MAX_SIZE)
+ header_row = next(ws.iter_rows(max_row=1, values_only=True), [])
+ fields = fix_headers(list(header_row)[:max_cols])
+ raw_rows = (
+ row[:max_cols] if row else []
+ for row in ws.iter_rows(min_row=2, values_only=True)
+ )
+ rows = _extract_rows(fields, raw_rows)
+ sheets[name] = (header_population(fields), rows)
+ return sheets
+
+
+def fix_headers(raw):
+ return [str(v) if v not in (None, '') else f'Unnamed: {i + 1}' for i, v in enumerate(raw)]
+
+
+def row_vals(row, datemode):
+ out = []
+ for c in row:
+ if c.ctype == xlrd.XL_CELL_DATE:
+ out.append(xlrd.xldate.xldate_as_datetime(c.value, datemode).isoformat())
+ else:
+ out.append(c.value)
+ return out
diff --git a/mfr/extensions/unoconv/export.py b/mfr/extensions/unoconv/export.py
index 2bff77d3a..55cf6b7a2 100644
--- a/mfr/extensions/unoconv/export.py
+++ b/mfr/extensions/unoconv/export.py
@@ -1,37 +1,40 @@
from http import HTTPStatus
from os.path import basename, splitext
-from subprocess import run, CalledProcessError
+from unoserver.client import UnoClient
from mfr.core.extension import BaseExporter
from mfr.core.exceptions import SubprocessError
-from mfr.extensions.unoconv.settings import (PORT,
- ADDRESS,
- UNOCONV_BIN,
- UNOCONV_TIMEOUT)
+from mfr.extensions.unoconv.settings import (
+ UNOSERVER_HOST,
+ UNOSERVER_PORT,
+)
class UnoconvExporter(BaseExporter):
+ """
+ Uses UnoClient (unoserver) to convert the source file into the requested format.
+ """
def export(self):
+ client = UnoClient(
+ server=UNOSERVER_HOST,
+ port=int(UNOSERVER_PORT),
+ )
try:
- run([
- UNOCONV_BIN,
- '-n',
- '-c', 'socket,host={},port={};urp;StarOffice.ComponentContext'.format(ADDRESS, PORT),
- '-f', self.format,
- '-o', self.output_file_path,
- '-vvv',
- self.source_file_path
- ], check=True, timeout=UNOCONV_TIMEOUT)
- except CalledProcessError as err:
+ client.convert(
+ inpath=self.source_file_path,
+ outpath=self.output_file_path,
+ convert_to=self.format,
+ )
+ except Exception as err:
name, extension = splitext(basename(self.source_file_path))
raise SubprocessError(
'Unable to export the file in the requested format, please try again later.',
- process='unoconv',
- cmd=str(err.cmd),
- returncode=err.returncode,
+ process='unoserver',
+ cmd=str(err),
+ returncode=None,
path=str(self.source_file_path),
code=HTTPStatus.BAD_REQUEST,
extension=extension or '',
- exporter_class='unoconv',
+ exporter_class='unoserver',
)
diff --git a/mfr/extensions/unoconv/render.py b/mfr/extensions/unoconv/render.py
index a872829db..62b13ddb7 100644
--- a/mfr/extensions/unoconv/render.py
+++ b/mfr/extensions/unoconv/render.py
@@ -1,18 +1,22 @@
+from dataclasses import dataclass
+import logging
import os
import furl
from mfr.core import utils
from mfr.core import extension
-
from mfr.extensions.unoconv import settings
+from mfr.tasks.serializer import serializable
+logger = logging.getLogger(__name__)
+@serializable
+@dataclass
class UnoconvRenderer(extension.BaseRenderer):
- def __init__(self, metadata, file_path, url, assets_url, export_url):
- super().__init__(metadata, file_path, url, assets_url, export_url)
-
+ def __post_init__(self):
+ super().__post_init__()
try:
self.map = settings.RENDER_MAP[self.metadata.ext]
except KeyError:
@@ -20,7 +24,7 @@ def __init__(self, metadata, file_path, url, assets_url, export_url):
self.export_file_path = self.file_path + self.map['renderer']
- exported_url = furl.furl(export_url)
+ exported_url = furl.furl(self.export_url)
exported_url.args['format'] = self.map['format']
exported_metadata = self.metadata
exported_metadata.download_url = exported_url.url
@@ -30,11 +34,10 @@ def __init__(self, metadata, file_path, url, assets_url, export_url):
exported_metadata,
self.export_file_path,
exported_url.url,
- assets_url,
- export_url
+ self.assets_url,
+ self.export_url
)
- # can't call file_required until renderer is built
self.renderer_metrics.add('file_required', self.file_required)
self.renderer_metrics.add('cache_result', self.cache_result)
@@ -45,24 +48,25 @@ def __init__(self, metadata, file_path, url, assets_url, export_url):
},
})
- def render(self):
+ def _render(self):
if self.renderer.file_required:
exporter = utils.make_exporter(
self.metadata.ext,
self.file_path,
self.export_file_path,
- self.map['format']
+ self.map['format'],
+ self.metadata,
)
exporter.export()
- rendition = self.renderer.render()
+ rendition = self.renderer._render()
self.metrics.add('subrenderer', self.renderer.renderer_metrics.serialize())
if self.renderer.file_required:
try:
os.remove(self.export_file_path)
except FileNotFoundError:
- pass
+ logger.warning(f"[render] Export file not found for cleanup: {self.export_file_path}")
return rendition
@@ -73,3 +77,6 @@ def file_required(self):
@property
def cache_result(self):
return self.renderer.cache_result
+
+ def use_celery(self) -> bool:
+ return True
diff --git a/mfr/extensions/unoconv/settings.py b/mfr/extensions/unoconv/settings.py
index 16bf05d6b..85d5e8049 100644
--- a/mfr/extensions/unoconv/settings.py
+++ b/mfr/extensions/unoconv/settings.py
@@ -2,15 +2,12 @@
from mfr import settings
+config = settings.child('UNOSERVER_EXTENSION_CONFIG')
-config = settings.child('UNOCONV_EXTENSION_CONFIG')
-
-UNOCONV_BIN = config.get('UNOCONV_BIN', '/usr/local/bin/unoconv')
-UNOCONV_TIMEOUT = int(config.get('UNOCONV_TIMEOUT', 60))
-
-ADDRESS = config.get('SERVER', os.environ.get('UNOCONV_PORT_2002_TCP_ADDR', '127.0.0.1'))
-PORT = config.get('PORT', os.environ.get('UNOCONV_PORT_2002_TCP_PORT', '2002'))
+UNOSERVER_TIMEOUT = int(config.get('TIMEOUT', 60))
+UNOSERVER_HOST = config.get('HOST', os.environ.get('UNOSERVER_INTERFACE', '127.0.0.1'))
+UNOSERVER_PORT = config.get('PORT', os.environ.get('UNOSERVER_PORT', '2003'))
DEFAULT_RENDER = {'renderer': '.pdf', 'format': 'pdf'}
RENDER_MAP = config.get_object('RENDER_MAP', {
diff --git a/mfr/extensions/utils.py b/mfr/extensions/utils.py
index ab43f5548..1a8b7ee52 100644
--- a/mfr/extensions/utils.py
+++ b/mfr/extensions/utils.py
@@ -1,5 +1,4 @@
import logging
-from typing import Tuple
from urllib.parse import parse_qs, urlencode, urlparse
from mfr.extensions import settings
@@ -7,7 +6,7 @@
logger = logging.getLogger(__name__)
-def munge_url_for_localdev(url: str) -> Tuple:
+def munge_url_for_localdev(url: str) -> tuple:
"""If MFR is being run in a local development environment (i.e. LOCAL_DEVELOPMENT is True), we
need to replace the internal host (the one the backend services communicate on, default:
192.168.168.167) with the external host (the one the user provides, default: "localhost")
@@ -23,13 +22,13 @@ def munge_url_for_localdev(url: str) -> Tuple:
url_obj = url_obj._replace(
query=urlencode(query_dict, doseq=True),
- netloc='{}:{}'.format(settings.LOCAL_HOST, url_obj.port)
+ netloc=f'{settings.LOCAL_HOST}:{url_obj.port}'
)
return url_obj
-def escape_url_for_template(url: str, logs: bool=True) -> str:
+def escape_url_for_template(url: str, logs: bool = True) -> str:
"""Escape (URL Encode) single and double quote(s) for the given URL.
Download and export URLs may end up not properly encoded right before they are about to be sent
diff --git a/mfr/extensions/video/render.py b/mfr/extensions/video/render.py
index 920d27959..eb2028e08 100644
--- a/mfr/extensions/video/render.py
+++ b/mfr/extensions/video/render.py
@@ -13,7 +13,7 @@ class VideoRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
download_url = munge_url_for_localdev(self.metadata.download_url)
safe_url = escape_url_for_template(download_url.geturl())
return self.TEMPLATE.render(url=safe_url)
diff --git a/mfr/extensions/zip/render.py b/mfr/extensions/zip/render.py
index a6370530c..fe89735e3 100644
--- a/mfr/extensions/zip/render.py
+++ b/mfr/extensions/zip/render.py
@@ -15,7 +15,7 @@ class ZipRenderer(extension.BaseRenderer):
os.path.join(os.path.dirname(__file__), 'templates')
]).get_template('viewer.mako')
- def render(self):
+ def _render(self):
zip_file = zipfile.ZipFile(self.file_path, 'r')
filelist = [{'name': markupsafe.escape(file.filename),
diff --git a/mfr/providers/__init__.py b/mfr/providers/__init__.py
index 5284146eb..e69de29bb 100644
--- a/mfr/providers/__init__.py
+++ b/mfr/providers/__init__.py
@@ -1 +0,0 @@
-__import__("pkg_resources").declare_namespace(__name__)
diff --git a/mfr/providers/http/provider.py b/mfr/providers/http/provider.py
index 3de83d05c..62acde32e 100644
--- a/mfr/providers/http/provider.py
+++ b/mfr/providers/http/provider.py
@@ -29,15 +29,15 @@ async def metadata(self):
return provider.ProviderMetadata(name, ext, content_type, unique_key, self.url)
async def download(self):
- response = await aiohttp.request('GET', self.url)
- if response.status >= 400:
- err_resp = await response.read()
- logger.error('Unable to download file: ({}) {}'.format(response.status, err_resp.decode('utf-8')))
- raise exceptions.DownloadError(
- 'Unable to download the requested file, please try again later.',
- download_url=self.url,
- response=await response.text(),
- code=response.status,
- provider='http',
- )
- return streams.ResponseStreamReader(response)
+ async with aiohttp.request('GET', self.url) as response:
+ if response.status >= 400:
+ err_resp = await response.read()
+ logger.error('Unable to download file: ({}) {}'.format(response.status, err_resp.decode('utf-8')))
+ raise exceptions.DownloadError(
+ 'Unable to download the requested file, please try again later.',
+ download_url=self.url,
+ response=await response.text(),
+ code=response.status,
+ provider='http',
+ )
+ return streams.ResponseStreamReader(response)
diff --git a/mfr/providers/osf/provider.py b/mfr/providers/osf/provider.py
index 4745e8ecc..cb7db7839 100644
--- a/mfr/providers/osf/provider.py
+++ b/mfr/providers/osf/provider.py
@@ -7,7 +7,7 @@
import furl
import aiohttp
-from aiohttp.errors import ContentEncodingError
+from aiohttp import ClientSession
from waterbutler.core import streams
@@ -59,7 +59,8 @@ async def metadata(self):
differently.
"""
download_url = await self._fetch_download_url()
- logger.debug('download_url::{}'.format(download_url))
+ logger.debug(f'download_url::{download_url}')
+ metadata = {}
if '/file?' in download_url:
# URL is for WaterButler v0 API
# TODO Remove this when API v0 is officially deprecated
@@ -67,6 +68,7 @@ async def metadata(self):
metadata_url = download_url.replace('/file?', '/data?', 1)
metadata_response = await self._make_request('GET', metadata_url)
metadata = await metadata_response.json()
+ await metadata_response.release()
else:
# URL is for WaterButler v1 API
self.metrics.add('metadata.wb_api', 'v1')
@@ -82,7 +84,7 @@ async def metadata(self):
if response_code != 200:
raise exceptions.MetadataError(
'Failed to fetch file metadata from WaterButler. Received response: ',
- 'code {} {}'.format(str(response_code), str(response_reason)),
+ f'code {str(response_code)} {str(response_reason)}',
metadata_url=download_url,
response=response_reason,
provider=self.NAME,
@@ -91,7 +93,7 @@ async def metadata(self):
try:
metadata = {'data': json.loads(response_headers['x-waterbutler-metadata'])['attributes']}
- except ContentEncodingError:
+ except Exception:
pass # hack: aiohttp tries to unzip empty body when Content-Encoding is set
self.metrics.add('metadata.raw', metadata)
@@ -127,7 +129,7 @@ async def metadata(self):
unique_key = hashlib.sha256((meta['etag'] + cleaned_url.url).encode('utf-8')).hexdigest()
stable_str = '/{}/{}{}'.format(meta['resource'], meta['provider'], meta['path'])
stable_id = hashlib.sha256(stable_str.encode('utf-8')).hexdigest()
- logger.debug('stable_identifier: str({}) hash({})'.format(stable_str, stable_id))
+ logger.debug(f'stable_identifier: str({stable_str}) hash({stable_id})')
return provider.ProviderMetadata(name, ext, content_type, unique_key, download_url, stable_id)
@@ -139,7 +141,8 @@ async def download(self):
if response.status >= 400:
resp_text = await response.text()
- logger.error('Unable to download file: ({}) {}'.format(response.status, resp_text))
+ await response.release()
+ logger.error(f'Unable to download file: ({response.status}) {resp_text}')
raise exceptions.DownloadError(
'Unable to download the requested file, please try again later.',
download_url=download_url,
@@ -150,8 +153,9 @@ async def download(self):
self.metrics.add('download.saw_redirect', False)
if response.status in (302, 301):
await response.release()
- response = await aiohttp.request('GET', response.headers['location'])
- self.metrics.add('download.saw_redirect', True)
+ async with aiohttp.request('GET', self.url) as response:
+ self.metrics.add('download.saw_redirect', True)
+ return streams.ResponseStreamReader(response)
return streams.ResponseStreamReader(response)
@@ -180,7 +184,7 @@ async def _fetch_download_url(self):
)
await request.release()
- logger.debug('osf-download-resolver: request.status::{}'.format(request.status))
+ logger.debug(f'osf-download-resolver: request.status::{request.status}')
if request.status != 302:
raise exceptions.MetadataError(
request.reason,
@@ -205,4 +209,4 @@ async def _make_request(self, method, url, *args, **kwargs):
if self.authorization:
kwargs.setdefault('headers', {})['Authorization'] = 'Bearer ' + self.token
- return await aiohttp.request(method, url, *args, **kwargs)
+ return await ClientSession()._request(method, url, *args, **kwargs)
diff --git a/mfr/server/app.py b/mfr/server/app.py
index d7f4b2abc..66a7e1fe3 100644
--- a/mfr/server/app.py
+++ b/mfr/server/app.py
@@ -7,7 +7,10 @@
import tornado.web
import tornado.httpserver
import tornado.platform.asyncio
-from raven.contrib.tornado import AsyncSentryClient
+
+import sentry_sdk
+from sentry_sdk.integrations.tornado import TornadoIntegration
+from sentry_sdk.integrations.logging import LoggingIntegration
from mfr import settings
from mfr.server import settings as server_settings
@@ -24,19 +27,29 @@
def sig_handler(sig, frame):
- io_loop = tornado.ioloop.IOLoop.instance()
+ """
+ https://stackoverflow.com/questions/34554247/python-tornado-i-o-loop-current-vs-instance-method
+ https://www.tornadoweb.org/en/branch6.3/_modules/tornado/testing.html
+ """
+ io_loop = tornado.ioloop.IOLoop.current()
+ loop = io_loop.asyncio_loop # Access the asyncio loop from Tornado
def stop_loop():
- if len(asyncio.Task.all_tasks(io_loop)) == 0:
- io_loop.stop()
- else:
+ """
+ Retrieve all tasks associated with tornado in asyncio loop
+ Todo: (maybe there is more explicit way to check than 'tornado' in repr(task))
+ """
+ exists_tornado_task = any(task for task in asyncio.all_tasks(loop) if 'tornado' in repr(task))
+ if exists_tornado_task:
io_loop.call_later(1, stop_loop)
+ else:
+ io_loop.stop()
io_loop.add_callback_from_signal(stop_loop)
def almost_apache_style_log(handler):
- '''without status code and body length'''
+ """without status code and body length"""
req = handler.request
access_logger.info('%s - - [%s +0800] "%s %s %s" - - "%s" "%s"' %
(req.remote_ip, time.strftime("%d/%b/%Y:%X"), req.method,
@@ -46,10 +59,19 @@ def almost_apache_style_log(handler):
def make_app(debug):
+ sentry_logging = LoggingIntegration(
+ level=logging.INFO, # Capture INFO level and above as breadcrumbs
+ event_level=None, # Do not send logs of any level as events
+ )
+ sentry_sdk.init(
+ dsn=settings.SENTRY_DSN,
+ release=__version__,
+ integrations=[TornadoIntegration(), sentry_logging, ],
+ )
app = tornado.web.Application(
[
(r'/static/(.*)', tornado.web.StaticFileHandler, {'path': server_settings.STATIC_PATH}),
- (r'/assets/(.*?)/(.*\..*)', ExtensionsStaticFileHandler),
+ (r'/assets/(?P[^/]+)/(?P.*)', ExtensionsStaticFileHandler),
(r'/export', ExportHandler),
(r'/exporters', ExportersHandler),
(r'/render', RenderHandler),
@@ -59,7 +81,6 @@ def make_app(debug):
debug=debug,
log_function=almost_apache_style_log,
)
- app.sentry_client = AsyncSentryClient(settings.SENTRY_DSN, release=__version__)
return app
@@ -83,7 +104,7 @@ def serve():
ssl_options=ssl_options,
)
- logger.info("Listening on {0}:{1}".format(server_settings.ADDRESS, server_settings.PORT))
+ logger.info(f"Listening on {server_settings.ADDRESS}:{server_settings.PORT}")
signal.signal(signal.SIGTERM, partial(sig_handler))
asyncio.get_event_loop().set_debug(server_settings.DEBUG)
diff --git a/mfr/server/handlers/core.py b/mfr/server/handlers/core.py
index 4c2bd067f..3375f3e19 100644
--- a/mfr/server/handlers/core.py
+++ b/mfr/server/handlers/core.py
@@ -1,13 +1,15 @@
-import os
import abc
+import pathlib
import uuid
import asyncio
import logging
-import pkg_resources
+import os
+
+from importlib.metadata import entry_points
import tornado.web
import tornado.iostream
-from raven.contrib.tornado import SentryMixin
+import sentry_sdk
import waterbutler.core.utils
import waterbutler.server.utils
@@ -76,7 +78,7 @@ def options(self):
self.set_header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE'),
-class BaseHandler(CorsMixin, tornado.web.RequestHandler, SentryMixin):
+class BaseHandler(CorsMixin, tornado.web.RequestHandler):
"""Base class for the Render and Export handlers. Fetches the file metadata for the file
indicated by the ``url`` query parameter and builds the provider caches. Also handles
writing output and errors.
@@ -93,9 +95,11 @@ def __init__(self, *args, **kwargs):
self.metrics = self.handler_metrics.new_subrecord(self.NAME)
self.extension_metrics = MetricsRecord('extension')
+ self.url = ''
- @abc.abstractproperty
+ @abc.abstractmethod
def NAME(self):
+ # Todo: not see Name implementation in child classes
raise NotImplementedError
async def prepare(self):
@@ -113,7 +117,7 @@ async def prepare(self):
provider=settings.PROVIDER_NAME,
code=400,
)
- logging.debug('target_url::{}'.format(self.url))
+ logging.debug(f'target_url::{self.url}')
self.provider = utils.make_provider(
settings.PROVIDER_NAME,
@@ -124,7 +128,7 @@ async def prepare(self):
self.metadata = await self.provider.metadata()
self.extension_metrics.add('ext', self.metadata.ext)
- logging.debug('extension::{}'.format(self.metadata.ext))
+ logging.debug(f'extension::{self.metadata.ext}')
self.cache_provider = waterbutler.core.utils.make_provider(
settings.CACHE_PROVIDER_NAME,
@@ -159,15 +163,26 @@ async def write_stream(self, stream):
return
def write_error(self, status_code, exc_info):
- self.captureException(exc_info) # Log all non 2XX codes to sentry
+
+ # TODO: verify that `exc_info` arg is compatible with tornado 6.4.2 sig
etype, exc, _ = exc_info
+ scope = sentry_sdk.get_current_scope()
+ scope.set_tag('class', etype.__name__)
+ scope.set_tag('status_code', status_code)
+ sentry_sdk.capture_exception(exc) # Log all non 2XX codes to sentry
if issubclass(etype, exceptions.PluginError):
try: # clever errors shouldn't break other things
current, child_type = {}, None
for level in reversed(exc.attr_stack):
if current:
- current = {'{}_{}'.format(level[0], child_type): current}
+ """
+ TODO: dictionary 'current' is reassigned in condition, Qodana code inspector may be
+ complaining because some data previously saved in the dictionary may be lost
+ (but maybe it is ok in terms of business logic),
+ As I understand the current accumulate previous current versions so it may be ok
+ """
+ current = {f'{level[0]}_{child_type}': current}
current['child_type'] = child_type
current.update(level[1])
current['self_type'] = level[0]
@@ -176,6 +191,7 @@ def write_error(self, status_code, exc_info):
current['materialized_type'] = '.'.join([x[0] for x in exc.attr_stack])
self.error_metrics = current
except Exception:
+ # Todo: maybe it is needed to use logger and specific message for exception logging
pass
self.set_status(exc.code)
self.finish(exc.as_html())
@@ -204,10 +220,9 @@ def write_error(self, status_code, exc_info):
def log_exception(self, typ, value, tb):
if isinstance(value, tornado.web.HTTPError):
if value.log_message:
- format = "%d %s: " + value.log_message
- args = ([value.status_code, self._request_summary()] +
- list(value.args))
- tornado.web.gen_log.warning(format, *args)
+ log_message_format = "%d %s: " + value.log_message
+ args = ([value.status_code, self._request_summary()] + list(value.args))
+ tornado.web.gen_log.warning(log_message_format, *args)
else:
tornado.web.app_log.error("[User-Agent: %s] Uncaught exception %s\n",
self.request.headers.get('User-Agent', '*none found*'),
@@ -282,16 +297,45 @@ class ExtensionsStaticFileHandler(tornado.web.StaticFileHandler, CorsMixin):
"""
def initialize(self):
- namespace = 'mfr.renderers'
- module_path = 'mfr.extensions'
- self.modules = {
- ep.module_name.replace(module_path + '.', ''): os.path.join(ep.dist.location, 'mfr', 'extensions', ep.module_name.replace(module_path + '.', ''), 'static')
- for ep in list(pkg_resources.iter_entry_points(namespace))
- }
+ # Todo: the method args differ in comparison with StaticFileHandler
+ namespace = "mfr.renderers"
+ module_path_prefix = "mfr.extensions"
+ self.modules = {}
+ root = pathlib.Path(os.path.abspath(__file__).split('mfr')[0])
+
+ for ep in entry_points().select(group=namespace):
+ fq_mod = ep.value.split(":")[0]
+ module = fq_mod.replace(f"{module_path_prefix}.", "").split(".")[0]
+ static_dir = root / "mfr" / "extensions" / module / "static"
+ if static_dir.is_dir():
+ self.modules[module] = static_dir.as_posix()
+ logger.debug(f"{module}: {static_dir}")
+
+ repo_root = pathlib.Path(__file__).resolve().parents[2]
+ ext_root = repo_root / "extensions"
+ if not ext_root.is_dir():
+ ext_root = repo_root.parent / "mfr" / "extensions"
+
+ for module_path in ext_root.iterdir():
+ static_dir = module_path / "static"
+ if static_dir.is_dir():
+ self.modules.setdefault(module_path.name, static_dir.as_posix())
+ logger.debug(f"{module_path.name}: {static_dir}")
+
+ async def get(self, module: str, path: str, **kwargs):
+ root = self.modules.get(module)
+ if not root:
+ while path:
+ module, path = path.split('/', maxsplit=1)
+ root = self.modules.get(module)
+ if root:
+ break
+ else:
+ self.set_status(404)
+ return
- async def get(self, module_name, path):
try:
- super().initialize(self.modules[module_name])
+ super().initialize(root)
return await super().get(path)
except Exception:
self.set_status(404)
diff --git a/mfr/server/handlers/export.py b/mfr/server/handlers/export.py
index 080499b8e..527ed929a 100644
--- a/mfr/server/handlers/export.py
+++ b/mfr/server/handlers/export.py
@@ -1,6 +1,7 @@
import asyncio
import logging
import os
+from urllib.parse import quote
from waterbutler.core.exceptions import InvalidParameters, DownloadError
import waterbutler.core.streams
@@ -23,29 +24,29 @@ async def prepare(self):
await super().prepare()
- format = self.request.query_arguments.get('format', None)
- if not format:
+ query_arguments_format = self.request.query_arguments.get('format', None)
+ if not query_arguments_format:
raise InvalidParameters("Invalid Request: Url requires query parameter 'format' with"
" appropriate extension")
# TODO: do we need to catch exceptions for decoding?
- self.format = format[0].decode('utf-8')
+ self.format = query_arguments_format[0].decode('utf-8')
self.exporter_name = utils.get_exporter_name(self.metadata.ext)
- self.cache_file_id = '{}.{}'.format(self.metadata.unique_key, self.format)
+ self.cache_file_id = f'{self.metadata.unique_key}.{self.format}'
if self.exporter_name:
- cache_file_path_str = '/export/{}.{}'.format(self.cache_file_id, self.exporter_name)
+ cache_file_path_str = f'/export/{self.cache_file_id}.{self.exporter_name}'
else:
- cache_file_path_str = '/export/{}'.format(self.cache_file_id)
+ cache_file_path_str = f'/export/{self.cache_file_id}'
self.cache_file_path = await self.cache_provider.validate_path(cache_file_path_str)
self.source_file_path = await self.local_cache_provider.validate_path(
- '/export/{}'.format(self.source_file_id)
+ f'/export/{self.source_file_id}'
)
- self.output_file_id = '{}.{}'.format(self.source_file_path.name, self.format)
+ self.output_file_id = f'{self.source_file_path.name}.{self.format}'
self.output_file_path = await self.local_cache_provider.validate_path(
- '/export/{}'.format(self.output_file_id)
+ f'/export/{self.output_file_id}'
)
self.metrics.merge({
'output_file': {
@@ -59,9 +60,9 @@ async def get(self):
"""Export a file to the format specified via the associated extension library"""
# File is already in the requested format
- if self.metadata.ext.lower() == ".{}".format(self.format.lower()):
+ if self.metadata.ext.lower() == f".{self.format.lower()}":
await self.write_stream(await self.provider.download())
- logger.info('Exported {} with no conversion.'.format(self.format))
+ logger.info(f'Exported {self.format} with no conversion.')
self.metrics.add('export.conversion', 'noop')
return
@@ -69,11 +70,11 @@ async def get(self):
try:
cached_stream = await self.cache_provider.download(self.cache_file_path)
except DownloadError as e:
- assert e.code == 404, 'Non-404 DownloadError {!r}'.format(e)
- logger.info('No cached file found; Starting export [{}]'.format(self.cache_file_path))
+ assert e.code == 404, f'Non-404 DownloadError {e!r}'
+ logger.info(f'No cached file found; Starting export [{self.cache_file_path}]')
self.metrics.add('cache_file.result', 'miss')
else:
- logger.info('Cached file found; Sending downstream [{}]'.format(self.cache_file_path))
+ logger.info(f'Cached file found; Sending downstream [{self.cache_file_path}]')
self.metrics.add('cache_file.result', 'hit')
self._set_headers()
return await self.write_stream(cached_stream)
@@ -118,6 +119,6 @@ async def _cache_and_clean(self):
pass
def _set_headers(self):
- self.set_header('Content-Disposition', 'attachment;filename="{}"'.format('{}.{}'.format(self.metadata.name.replace('"', '\\"'), self.format)))
+ self.set_header('Content-Disposition', f'attachment;filename*=UTF-8\'\'{quote(self.metadata.name.replace('"', '\\"'))}.{self.format}')
if self.metadata.content_type:
self.set_header('Content-Type', self.metadata.content_type)
diff --git a/mfr/server/handlers/exporters.py b/mfr/server/handlers/exporters.py
index 1bea4694d..13cb2c471 100644
--- a/mfr/server/handlers/exporters.py
+++ b/mfr/server/handlers/exporters.py
@@ -1,4 +1,4 @@
-import pkg_resources
+from importlib.metadata import entry_points
import tornado.web
@@ -8,7 +8,7 @@ def get(self):
"""List available exporters"""
exporters = {}
- for ep in pkg_resources.iter_entry_points(group='mfr.exporters'):
+ for ep in entry_points().select(group='mfr.exporters'):
exporters.update({ep.name: ep.load().__name__})
self.write({
diff --git a/mfr/server/handlers/render.py b/mfr/server/handlers/render.py
index a8c75419a..025c48a42 100644
--- a/mfr/server/handlers/render.py
+++ b/mfr/server/handlers/render.py
@@ -1,5 +1,5 @@
+import http
import os
-import asyncio
import logging
import waterbutler.core.streams
@@ -29,13 +29,13 @@ async def prepare(self):
self.cache_file_id = self.metadata.unique_key
if self.renderer_name:
- cache_file_path_str = '/export/{}.{}'.format(self.cache_file_id, self.renderer_name)
+ cache_file_path_str = f'/export/{self.cache_file_id}.{self.renderer_name}'
else:
- cache_file_path_str = '/export/{}'.format(self.cache_file_id)
+ cache_file_path_str = f'/export/{self.cache_file_id}'
self.cache_file_path = await self.cache_provider.validate_path(cache_file_path_str)
self.source_file_path = await self.local_cache_provider.validate_path(
- '/render/{}'.format(self.source_file_id)
+ f'/render/{self.source_file_id}'
)
async def get(self):
@@ -45,7 +45,7 @@ async def get(self):
self.metadata,
self.source_file_path.full_path,
self.url,
- '{}://{}/assets'.format(self.request.protocol, self.request.host),
+ f'{self.request.protocol}://{self.request.host}/assets',
self.request.uri.replace('/render?', '/export?', 1)
)
@@ -55,11 +55,11 @@ async def get(self):
try:
cached_stream = await self.cache_provider.download(self.cache_file_path)
except waterbutler.core.exceptions.DownloadError as e:
- assert e.code == 404, 'Non-404 DownloadError {!r}'.format(e)
- logger.info('No cached file found; Starting render [{}]'.format(self.cache_file_path))
+ assert e.code == 404, f'Non-404 DownloadError {e!r}'
+ logger.info(f'No cached file found; Starting render [{self.cache_file_path}]')
self.metrics.add('cache_file.result', 'miss')
else:
- logger.info('Cached file found; Sending downstream [{}]'.format(self.cache_file_path))
+ logger.info(f'Cached file found; Sending downstream [{self.cache_file_path}]')
self.metrics.add('cache_file.result', 'hit')
return await self.write_stream(cached_stream)
@@ -71,20 +71,14 @@ async def get(self):
else:
self.metrics.add('source_file.upload.required', False)
- loop = asyncio.get_event_loop()
- rendition = await loop.run_in_executor(None, renderer.render)
+ rendition = await renderer.render()
self.renderer_metrics = renderer.renderer_metrics
-
- # Spin off upload into non-blocking operation
- if renderer.cache_result and settings.CACHE_ENABLED:
- asyncio.ensure_future(
- self.cache_provider.upload(
- waterbutler.core.streams.StringStream(rendition),
- self.cache_file_path
- )
- )
-
- await self.write_stream(waterbutler.core.streams.StringStream(rendition))
+ if rendition:
+ await self.write_stream(rendition)
+ else:
+ self.set_status(http.HTTPStatus.ACCEPTED)
+ await self.write("Accepted")
+ await self.flush()
async def _cache_and_clean(self):
if hasattr(self, 'source_file_path'):
diff --git a/mfr/server/handlers/renderers.py b/mfr/server/handlers/renderers.py
index 572e08365..dedbf3d6c 100644
--- a/mfr/server/handlers/renderers.py
+++ b/mfr/server/handlers/renderers.py
@@ -1,4 +1,4 @@
-import pkg_resources
+from importlib.metadata import entry_points
import tornado.web
@@ -8,7 +8,7 @@ def get(self):
"""List available renderers"""
renderers = {}
- for ep in pkg_resources.iter_entry_points(group='mfr.renderers'):
+ for ep in entry_points().select(group='mfr.renderers'):
renderers.update({ep.name: ep.load().__name__})
self.write({
diff --git a/mfr/settings.py b/mfr/settings.py
index 7dd613ad4..2d63c6b51 100644
--- a/mfr/settings.py
+++ b/mfr/settings.py
@@ -41,9 +41,9 @@ def __init__(self, *args, parent=None, **kwargs):
def get(self, key, default=None):
"""Fetch a config value for ``key`` from the settings. First checks the env, then the
on-disk config. If neither exists, returns ``default``."""
- env = self.full_key(key)
- if env in os.environ:
- return os.environ.get(env)
+ environ = self.full_key(key)
+ if environ in os.environ:
+ return os.environ.get(environ)
return super().get(key, default)
def get_bool(self, key, default=None):
@@ -80,7 +80,7 @@ def get_object(self, key, default=None):
def full_key(self, key):
"""The name of the envvar which corresponds to this key."""
- return '{}_{}'.format(self.parent, key) if self.parent else key
+ return f'{self.parent}_{key}' if self.parent else key
def child(self, key):
"""Fetch a sub-dict of the current dict."""
@@ -146,16 +146,16 @@ def child(self, key):
try:
- config_path = os.environ['{}_CONFIG'.format(PROJECT_NAME.upper())]
+ config_path = os.environ[f'{PROJECT_NAME.upper()}_CONFIG']
except KeyError:
env = os.environ.get('ENV', 'test')
- config_path = '{}/{}-{}.json'.format(PROJECT_CONFIG_PATH, PROJECT_NAME, env)
+ config_path = f'{PROJECT_CONFIG_PATH}/{PROJECT_NAME}-{env}.json'
config = SettingsDict()
config_path = os.path.expanduser(config_path)
if not os.path.exists(config_path):
- logging.warning('No \'{}\' configuration file found'.format(config_path))
+ logging.warning(f'No \'{config_path}\' configuration file found')
else:
with open(os.path.expanduser(config_path)) as fp:
config = SettingsDict(json.load(fp))
diff --git a/mfr/tasks/__init__.py b/mfr/tasks/__init__.py
new file mode 100644
index 000000000..7dee91fdb
--- /dev/null
+++ b/mfr/tasks/__init__.py
@@ -0,0 +1,13 @@
+from mfr.tasks.app import app
+from mfr.tasks.core import celery_task
+from mfr.tasks.core import backgrounded
+from mfr.tasks.core import wait_on_celery
+from mfr.tasks.exceptions import WaitTimeOutError
+
+__all__ = [
+ 'app',
+ 'celery_task',
+ 'backgrounded',
+ 'wait_on_celery',
+ 'WaitTimeOutError',
+]
diff --git a/mfr/tasks/app.py b/mfr/tasks/app.py
new file mode 100644
index 000000000..4ad3321ba
--- /dev/null
+++ b/mfr/tasks/app.py
@@ -0,0 +1,44 @@
+import logging
+
+from celery import Celery
+from celery.signals import task_failure
+
+import sentry_sdk
+from sentry_sdk.integrations.celery import CeleryIntegration
+from sentry_sdk.integrations.logging import LoggingIntegration
+
+from mfr.settings import config
+from mfr.version import __version__
+from mfr.tasks import settings as tasks_settings
+
+logger = logging.getLogger(__name__)
+
+app = Celery()
+app.config_from_object(tasks_settings)
+
+
+def register_signal():
+ """Adapted from `raven.contrib.celery.register_signal`. Remove args and
+ kwargs from logs so that keys aren't leaked to Sentry.
+ """
+ def process_failure_signal(sender, task_id, *args, **kwargs):
+ scope = sentry_sdk.get_current_scope()
+ scope.set_tag('task_id', task_id)
+ scope.set_tag('task', sender)
+ sentry_sdk.capture_exception()
+
+ task_failure.connect(process_failure_signal, weak=False)
+
+
+sentry_dsn = config.get_nullable('SENTRY_DSN', None)
+if sentry_dsn:
+ sentry_logging = LoggingIntegration(
+ level=logging.INFO, # Capture INFO level and above as breadcrumbs
+ event_level=None, # Do not send logs of any level as events
+ )
+ sentry_sdk.init(
+ sentry_dsn,
+ release=__version__,
+ integrations=[CeleryIntegration(), sentry_logging]
+ )
+ register_signal()
diff --git a/mfr/tasks/core.py b/mfr/tasks/core.py
new file mode 100644
index 000000000..59a6342a9
--- /dev/null
+++ b/mfr/tasks/core.py
@@ -0,0 +1,135 @@
+import os
+import pickle
+import asyncio
+import logging
+import functools
+
+from celery.backends.base import DisabledBackend
+
+from mfr.tasks.app import app
+from mfr.tasks import settings
+from mfr.tasks import exceptions
+
+logger = logging.getLogger(__name__)
+
+
+def ensure_event_loop():
+ """Ensure the existance of an eventloop
+ Useful for contexts where get_event_loop() may
+ raise an exception.
+ :returns: The new event loop
+ :rtype: BaseEventLoop
+ """
+ try:
+ return asyncio.get_event_loop()
+ except (AssertionError, RuntimeError):
+ asyncio.set_event_loop(asyncio.new_event_loop())
+
+ # Note: No clever tricks are used here to dry up code
+ # This avoids an infinite loop if settings the event loop ever fails
+ return asyncio.get_event_loop()
+
+
+def __coroutine_unwrapper(func):
+ @functools.wraps(func)
+ def wrapped(*args, **kwargs):
+ return ensure_event_loop().run_until_complete(func(*args, **kwargs))
+ wrapped.as_async = func
+ return wrapped
+
+
+async def backgrounded(func, *args, **kwargs):
+ """Runs the given function with the given arguments in
+ a background thread
+ """
+ loop = asyncio.get_event_loop()
+ if asyncio.iscoroutinefunction(func):
+ func = __coroutine_unwrapper(func)
+
+ return (await loop.run_in_executor(
+ None, # None uses the default executer, ThreadPoolExecuter
+ functools.partial(func, *args, **kwargs)
+ ))
+
+
+def backgroundify(func):
+ @functools.wraps(func)
+ async def wrapped(*args, **kwargs):
+ return await backgrounded(func, *args, **kwargs)
+ return wrapped
+
+
+def adhoc_file_backend(func, was_bound=False, basepath=None):
+ basepath = basepath or settings.ADHOC_BACKEND_PATH
+
+ @functools.wraps(func)
+ def wrapped(task, *args, **kwargs):
+ if was_bound:
+ args = (task,) + args
+
+ try:
+ result = func(*args, **kwargs)
+ except Exception as e:
+ result = e
+
+ with open(os.path.join(basepath, task.request.id), 'wb') as result_file:
+ pickle.dump(result, result_file)
+
+ if isinstance(result, Exception):
+ raise result
+ return result
+ return wrapped
+
+
+def celery_task(func, *args, **kwargs):
+ """A wrapper around Celery.task. When the wrapped method is called it will be called using
+ Celery's Task.delay function and run in a background thread.
+
+ If the celery backend is disabled, the task will be wrapped in a function that will write the
+ result to disk using the pickle serialization protocol.
+ """
+ task_func = __coroutine_unwrapper(func)
+
+ if isinstance(app.backend, DisabledBackend):
+ task_func = adhoc_file_backend(
+ task_func,
+ was_bound=kwargs.pop('bind', False)
+ )
+ kwargs['bind'] = True
+
+ logger.debug(f'celery_task: task_func:({task_func})')
+
+ task = app.task(task_func, **kwargs)
+ task.adelay = backgroundify(task.delay)
+
+ return task
+
+
+@backgroundify
+async def wait_on_celery(result, interval=None, timeout=None, basepath=None):
+ timeout = timeout or settings.WAIT_TIMEOUT
+ interval = interval or settings.WAIT_INTERVAL
+ basepath = basepath or settings.ADHOC_BACKEND_PATH
+
+ waited = 0
+
+ while True:
+ if isinstance(app.backend, DisabledBackend):
+ try:
+ with open(os.path.join(basepath, result.id), 'rb') as result_file:
+ data = pickle.load(result_file)
+ if isinstance(data, Exception):
+ raise data
+ return data
+ except FileNotFoundError:
+ pass
+ else:
+ if result.ready():
+ if result.failed():
+ raise result.result
+ return result.result
+
+ if waited > timeout:
+ raise exceptions.WaitTimeOutError
+ await asyncio.sleep(interval)
+ waited += interval
diff --git a/mfr/tasks/exceptions.py b/mfr/tasks/exceptions.py
new file mode 100644
index 000000000..46ddb8f21
--- /dev/null
+++ b/mfr/tasks/exceptions.py
@@ -0,0 +1,6 @@
+class MfrTaskError(Exception):
+ pass
+
+
+class WaitTimeOutError(MfrTaskError):
+ pass
diff --git a/mfr/tasks/export.py b/mfr/tasks/export.py
new file mode 100644
index 000000000..a7dee9313
--- /dev/null
+++ b/mfr/tasks/export.py
@@ -0,0 +1,10 @@
+import logging
+
+from mfr.tasks import core
+
+logger = logging.getLogger(__name__)
+
+
+@core.celery_task
+async def export(exporter):
+ exporter.do_export()
diff --git a/mfr/tasks/render.py b/mfr/tasks/render.py
new file mode 100644
index 000000000..deee8a3bd
--- /dev/null
+++ b/mfr/tasks/render.py
@@ -0,0 +1,10 @@
+import logging
+
+from mfr.extensions.unoconv import UnoconvRenderer
+from mfr.tasks import core
+logger = logging.getLogger(__name__)
+
+
+@core.celery_task
+async def render(renderer: UnoconvRenderer):
+ await renderer.do_render()
diff --git a/mfr/tasks/serializer.py b/mfr/tasks/serializer.py
new file mode 100644
index 000000000..32778e4c5
--- /dev/null
+++ b/mfr/tasks/serializer.py
@@ -0,0 +1,116 @@
+import copy
+import types
+from dataclasses import is_dataclass, fields
+
+import kombu.utils.json
+
+__registry = {}
+
+_ATOMIC_TYPES = frozenset({
+ # Common JSON Serializable types
+ types.NoneType,
+ bool,
+ int,
+ float,
+ str,
+ # Other common types
+ complex,
+ bytes,
+ # Other types that are also unaffected by deepcopy
+ types.EllipsisType,
+ types.NotImplementedType,
+ types.CodeType,
+ types.BuiltinFunctionType,
+ types.FunctionType,
+ type,
+ range,
+ property,
+})
+
+
+def serialize(obj, *, dict_factory=dict):
+ if not is_dataclass(obj):
+ raise TypeError("asdict() should be called on dataclass instances")
+ return _asdict_inner(obj, dict_factory)
+
+
+def _asdict_inner(obj, dict_factory):
+ obj_type = type(obj)
+ if obj_type in _ATOMIC_TYPES:
+ return obj
+ elif is_dataclass(obj_type):
+ # dataclass instance: fast path for the common case
+ if obj_type.__name__ not in __registry:
+ raise TypeError('cannot serialize non-serializable class')
+ if dict_factory is dict:
+ return {
+ f.name: _asdict_inner(getattr(obj, f.name), dict)
+ for f in fields(obj)
+ } | {'__type': obj_type.__name__}
+ else:
+ return dict_factory([
+ (f.name, _asdict_inner(getattr(obj, f.name), dict_factory))
+ for f in fields(obj)
+ ]) | {'__type': obj_type.__name__}
+ elif obj_type is list:
+ return [_asdict_inner(v, dict_factory) for v in obj]
+ elif obj_type is dict:
+ return {
+ _asdict_inner(k, dict_factory): _asdict_inner(v, dict_factory)
+ for k, v in obj.items()
+ }
+ elif obj_type is tuple:
+ return tuple([_asdict_inner(v, dict_factory) for v in obj])
+ elif issubclass(obj_type, tuple):
+ if hasattr(obj, '_fields'):
+ return obj_type(*[_asdict_inner(v, dict_factory) for v in obj])
+ else:
+ return obj_type(_asdict_inner(v, dict_factory) for v in obj)
+ elif issubclass(obj_type, dict):
+ if hasattr(obj_type, 'default_factory'):
+ result = obj_type(obj.default_factory)
+ for k, v in obj.items():
+ result[_asdict_inner(k, dict_factory)] = _asdict_inner(v, dict_factory)
+ return result
+ return obj_type((_asdict_inner(k, dict_factory),
+ _asdict_inner(v, dict_factory))
+ for k, v in obj.items())
+ elif issubclass(obj_type, list):
+ return obj_type(_asdict_inner(v, dict_factory) for v in obj)
+ else:
+ return copy.deepcopy(obj)
+
+
+def serializable(cls):
+ assert is_dataclass(cls), f'class {cls.__name__} is not a dataclass, therefore cannot be serializable'
+ assert cls.__name__ not in __registry, 'This class has already been registered'
+ __registry[cls.__name__] = cls
+
+ kombu.utils.json.register_type(
+ cls,
+ cls.__name__,
+ serialize,
+ deserialize,
+ )
+ return cls
+
+
+def deserialize(data):
+ if isinstance(data, list):
+ return [deserialize(item) for item in data]
+ if isinstance(data, dict):
+ data_type = data.pop('__type', None)
+ if not data_type:
+ raise TypeError('invalid deserialize payload')
+ if data_type not in __registry:
+ raise TypeError(f'type provided but type {data_type.__name__} is not declared serializable')
+ data_type = __registry.get(data_type)
+ for field in fields(data_type):
+ if is_dataclass(field.type) or isinstance(field.type, list):
+ data[field.name] = deserialize(data[field.name])
+ return data_type(**data)
+
+ raise TypeError(f'Cannot deserialize type {type(data)}')
+
+
+__all__ = ['serializable']
diff --git a/mfr/tasks/settings.py b/mfr/tasks/settings.py
new file mode 100644
index 000000000..47c173d74
--- /dev/null
+++ b/mfr/tasks/settings.py
@@ -0,0 +1,40 @@
+import os
+
+from kombu import Queue, Exchange
+
+from mfr import settings
+
+
+config = settings.child('TASKS_CONFIG')
+
+WAIT_TIMEOUT = int(config.get('WAIT_TIMEOUT', 20))
+WAIT_INTERVAL = float(config.get('WAIT_INTERVAL', 0.5))
+ADHOC_BACKEND_PATH = config.get('ADHOC_BACKEND_PATH', '/tmp')
+
+broker_url = config.get(
+ 'BROKER_URL',
+ 'amqp://{}:{}//'.format(
+ os.environ.get('RABBITMQ_PORT_5672_TCP_ADDR', ''),
+ os.environ.get('RABBITMQ_PORT_5672_TCP_PORT', ''),
+ )
+)
+
+task_default_queue = config.get('CELERY_DEFAULT_QUEUE', 'mfr')
+task_queues = (
+ Queue('mfr', Exchange('mfr'), routing_key='mfr'),
+)
+
+task_always_eager = config.get_bool('CELERY_ALWAYS_EAGER', False)
+result_backend = config.get_nullable('CELERY_RESULT_BACKEND', 'rpc://')
+result_persistent = config.get_bool('CELERY_RESULT_PERSISTENT', True)
+worker_disable_rate_limits = config.get_bool('CELERY_DISABLE_RATE_LIMITS', True)
+result_expires = int(config.get('CELERY_TASK_RESULT_EXPIRES', 60))
+task_create_missing_queues = config.get_bool('CELERY_CREATE_MISSING_QUEUES', False)
+task_acks_late = True
+worker_hijack_root_logger = False
+task_eager_propagates = True
+
+imports = [
+ "mfr.tasks.export",
+ "mfr.tasks.render",
+]
diff --git a/poetry.lock b/poetry.lock
new file mode 100644
index 000000000..8103da5d0
--- /dev/null
+++ b/poetry.lock
@@ -0,0 +1,4710 @@
+# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
+
+[[package]]
+name = "agent"
+version = "0.1.2"
+description = "Async generators for humans"
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "agent-0.1.2.tar.gz", hash = "sha256:75e2654c40fd149c8f19f97da36d1f3818750571e6f1e734e1fb397d56a19e66"},
+]
+
+[[package]]
+name = "aggdraw"
+version = "1.3.19"
+description = "High quality drawing interface for PIL."
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "aggdraw-1.3.19-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:cfbb072ee0a6de6cb6a782724df6e8ab9648d9566fb033118dcebbe9dc06326e"},
+ {file = "aggdraw-1.3.19-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:789fc905d0bad232fe4d783ee115ed34a1c0904957dc384fc5c45a40df517975"},
+ {file = "aggdraw-1.3.19-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30d783a7bfb2ff2ac43ce080ff18fb5df8b96ad4c0988c88324037855310e665"},
+ {file = "aggdraw-1.3.19-cp310-cp310-win_amd64.whl", hash = "sha256:4483393bc69392287d1c8159a0c475c51ce2f687b1099d686a3c5b2028e25b0f"},
+ {file = "aggdraw-1.3.19-cp310-cp310-win_arm64.whl", hash = "sha256:67f28103a619ebf7068421dfee7bd3d6cf2528887bfb5d16ecf952da10fd6f93"},
+ {file = "aggdraw-1.3.19-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a9b6be919955e9ace24a22ca1172786902254db22f6789a0bb8ce08bfb86603f"},
+ {file = "aggdraw-1.3.19-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c350f9403749e2fa33525bf9116a154ea5c7fddbb9fe045448b7700b62d882d"},
+ {file = "aggdraw-1.3.19-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5c47a5a4c9d1e0902b90b8b0032db55c8dc041dfc5005ff02749d8e9c0aa622"},
+ {file = "aggdraw-1.3.19-cp311-cp311-win_amd64.whl", hash = "sha256:b3bace3619f78891dbbeb1273409ea35d104880e5c22b0435808508c4c2f6a0e"},
+ {file = "aggdraw-1.3.19-cp311-cp311-win_arm64.whl", hash = "sha256:178784eb812dacfe3069fcbe4f4ef11877130803141b8f41b89535fbec0d0759"},
+ {file = "aggdraw-1.3.19-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:e68afe82d0bbd111b2d6d7f41ac8cf13a010cd65ad095117c2e9fd8252710a73"},
+ {file = "aggdraw-1.3.19-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f3ff2595490b3760658a28afdca5111ed787bd1fccdab5c81d0ea57e0fe5a8c"},
+ {file = "aggdraw-1.3.19-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56bbcc8d4f64e60ed815419837b9d2ba579169d92c4fe19e4caa3679aaedb6aa"},
+ {file = "aggdraw-1.3.19-cp312-cp312-win_amd64.whl", hash = "sha256:6a39bdf2f1043ca4148a926e35feaa1d4d592c25c8b225d8d0ad945415bab7cc"},
+ {file = "aggdraw-1.3.19-cp312-cp312-win_arm64.whl", hash = "sha256:21f951129b3014b3cf678b250ba5e4345d93243602b4062804e6111319d0eaf3"},
+ {file = "aggdraw-1.3.19-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f7cb8141620ec4cb3be55601115126d9a1b084ef5bdea0bb510007efa42e8cfe"},
+ {file = "aggdraw-1.3.19-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aecacc4f6d13b8343ac07624576bab4dadd4528f0c47f54b2fae0656fc913670"},
+ {file = "aggdraw-1.3.19-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:981210dbcbb649d80763a8ae32b845ff517103718c6bb0a95bae5b9d5d1c8cd2"},
+ {file = "aggdraw-1.3.19-cp313-cp313-win_amd64.whl", hash = "sha256:41e09faf469cae11339f5d1b0680dba7ec02502efebc10086f1a142a8a39afb8"},
+ {file = "aggdraw-1.3.19-cp313-cp313-win_arm64.whl", hash = "sha256:e5552ac136225692a774d481a9baa0736c68739f64b7a7ec9f4cc5f69c8a789a"},
+ {file = "aggdraw-1.3.19-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:e49048918017c62ba7069d781b351d4cbe8b188c76fe9104a923e57ddc95d5d0"},
+ {file = "aggdraw-1.3.19-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13a91cb1fdf32f7e5611212987901400297098c6aa403fd59bb3221ce4608663"},
+ {file = "aggdraw-1.3.19-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f79e9504e5fead1881d0bc3b763b76fb17f649ef263cfc1d63a10a068e904f3"},
+ {file = "aggdraw-1.3.19-cp39-cp39-win_amd64.whl", hash = "sha256:868c10d59daf9c6f625c4a206f384c637fdafe527c56c081bb0e567fcef17b55"},
+ {file = "aggdraw-1.3.19-cp39-cp39-win_arm64.whl", hash = "sha256:f0a4fd88d737719071cbfb1eba7520ca6e64c118b71b72525944b8d7bb20327c"},
+ {file = "aggdraw-1.3.19.tar.gz", hash = "sha256:e78a23b29fb66a079832bae5604f082bfa4ff9d5d469c77506a67253d7fee7db"},
+]
+
+[[package]]
+name = "aiobotocore"
+version = "2.24.2"
+description = "Async client for aws services using botocore and aiohttp"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "aiobotocore-2.24.2-py3-none-any.whl", hash = "sha256:808c63b2bd344b91e2f2acb874831118a9f53342d248acd16a68455a226e283a"},
+ {file = "aiobotocore-2.24.2.tar.gz", hash = "sha256:dfb21bdb2610e8de4d22f401e91a24d50f1330a302d03c62c485757becd439a9"},
+]
+
+[package.dependencies]
+aiohttp = ">=3.9.2,<4.0.0"
+aioitertools = ">=0.5.1,<1.0.0"
+botocore = ">=1.40.15,<1.40.19"
+jmespath = ">=0.7.1,<2.0.0"
+multidict = ">=6.0.0,<7.0.0"
+python-dateutil = ">=2.1,<3.0.0"
+wrapt = ">=1.10.10,<2.0.0"
+
+[package.extras]
+awscli = ["awscli (>=1.42.15,<1.42.19)"]
+boto3 = ["boto3 (>=1.40.15,<1.40.19)"]
+httpx = ["httpx (>=0.25.1,<0.29)"]
+
+[[package]]
+name = "aiocontextvars"
+version = "0.2.2"
+description = "Asyncio support for PEP-567 contextvars backport."
+optional = false
+python-versions = ">=3.5"
+groups = ["main"]
+files = [
+ {file = "aiocontextvars-0.2.2-py2.py3-none-any.whl", hash = "sha256:885daf8261818767d8f7cbd79f9d4482d118f024b6586ef6e67980236a27bfa3"},
+ {file = "aiocontextvars-0.2.2.tar.gz", hash = "sha256:f027372dc48641f683c559f247bd84962becaacdc9ba711d583c3871fb5652aa"},
+]
+
+[[package]]
+name = "aiohappyeyeballs"
+version = "2.6.1"
+description = "Happy Eyeballs for asyncio"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"},
+ {file = "aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558"},
+]
+
+[[package]]
+name = "aiohttp"
+version = "3.10.5"
+description = "Async http client/server framework (asyncio)"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3"},
+ {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6"},
+ {file = "aiohttp-3.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699"},
+ {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6"},
+ {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1"},
+ {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f"},
+ {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb"},
+ {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91"},
+ {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f"},
+ {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c"},
+ {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69"},
+ {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3"},
+ {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683"},
+ {file = "aiohttp-3.10.5-cp310-cp310-win32.whl", hash = "sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef"},
+ {file = "aiohttp-3.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088"},
+ {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2"},
+ {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf"},
+ {file = "aiohttp-3.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e"},
+ {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77"},
+ {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061"},
+ {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697"},
+ {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7"},
+ {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0"},
+ {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5"},
+ {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e"},
+ {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1"},
+ {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277"},
+ {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058"},
+ {file = "aiohttp-3.10.5-cp311-cp311-win32.whl", hash = "sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072"},
+ {file = "aiohttp-3.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff"},
+ {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487"},
+ {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a"},
+ {file = "aiohttp-3.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d"},
+ {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75"},
+ {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178"},
+ {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e"},
+ {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f"},
+ {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73"},
+ {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf"},
+ {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820"},
+ {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca"},
+ {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91"},
+ {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6"},
+ {file = "aiohttp-3.10.5-cp312-cp312-win32.whl", hash = "sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12"},
+ {file = "aiohttp-3.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc"},
+ {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092"},
+ {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77"},
+ {file = "aiohttp-3.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385"},
+ {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972"},
+ {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16"},
+ {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6"},
+ {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa"},
+ {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689"},
+ {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57"},
+ {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f"},
+ {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599"},
+ {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5"},
+ {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987"},
+ {file = "aiohttp-3.10.5-cp313-cp313-win32.whl", hash = "sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04"},
+ {file = "aiohttp-3.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022"},
+ {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569"},
+ {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a"},
+ {file = "aiohttp-3.10.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc"},
+ {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3"},
+ {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf"},
+ {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe"},
+ {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5"},
+ {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471"},
+ {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589"},
+ {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae"},
+ {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d"},
+ {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f"},
+ {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511"},
+ {file = "aiohttp-3.10.5-cp38-cp38-win32.whl", hash = "sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a"},
+ {file = "aiohttp-3.10.5-cp38-cp38-win_amd64.whl", hash = "sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8"},
+ {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e"},
+ {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172"},
+ {file = "aiohttp-3.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b"},
+ {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b"},
+ {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92"},
+ {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22"},
+ {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f"},
+ {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32"},
+ {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce"},
+ {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db"},
+ {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b"},
+ {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857"},
+ {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11"},
+ {file = "aiohttp-3.10.5-cp39-cp39-win32.whl", hash = "sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1"},
+ {file = "aiohttp-3.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862"},
+ {file = "aiohttp-3.10.5.tar.gz", hash = "sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691"},
+]
+
+[package.dependencies]
+aiohappyeyeballs = ">=2.3.0"
+aiosignal = ">=1.1.2"
+attrs = ">=17.3.0"
+frozenlist = ">=1.1.1"
+multidict = ">=4.5,<7.0"
+yarl = ">=1.0,<2.0"
+
+[package.extras]
+speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.2.0) ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""]
+
+[[package]]
+name = "aioitertools"
+version = "0.12.0"
+description = "itertools and builtins for AsyncIO and mixed iterables"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "aioitertools-0.12.0-py3-none-any.whl", hash = "sha256:fc1f5fac3d737354de8831cbba3eb04f79dd649d8f3afb4c5b114925e662a796"},
+ {file = "aioitertools-0.12.0.tar.gz", hash = "sha256:c2a9055b4fbb7705f561b9d86053e8af5d10cc845d22c32008c43490b2d8dd6b"},
+]
+
+[package.extras]
+dev = ["attribution (==1.8.0)", "black (==24.8.0)", "build (>=1.2)", "coverage (==7.6.1)", "flake8 (==7.1.1)", "flit (==3.9.0)", "mypy (==1.11.2)", "ufmt (==2.7.1)", "usort (==1.0.8.post1)"]
+docs = ["sphinx (==8.0.2)", "sphinx-mdinclude (==0.6.2)"]
+
+[[package]]
+name = "aiosignal"
+version = "1.4.0"
+description = "aiosignal: a list of registered asynchronous callbacks"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e"},
+ {file = "aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7"},
+]
+
+[package.dependencies]
+frozenlist = ">=1.1.0"
+
+[[package]]
+name = "alabaster"
+version = "1.0.0"
+description = "A light, configurable Sphinx theme"
+optional = false
+python-versions = ">=3.10"
+groups = ["docs"]
+files = [
+ {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"},
+ {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"},
+]
+
+[[package]]
+name = "amqp"
+version = "5.3.1"
+description = "Low-level AMQP client for Python (fork of amqplib)."
+optional = false
+python-versions = ">=3.6"
+groups = ["main"]
+files = [
+ {file = "amqp-5.3.1-py3-none-any.whl", hash = "sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2"},
+ {file = "amqp-5.3.1.tar.gz", hash = "sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432"},
+]
+
+[package.dependencies]
+vine = ">=5.0.0,<6.0.0"
+
+[[package]]
+name = "anyio"
+version = "4.11.0"
+description = "High-level concurrency and networking framework on top of asyncio or Trio"
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "anyio-4.11.0-py3-none-any.whl", hash = "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc"},
+ {file = "anyio-4.11.0.tar.gz", hash = "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4"},
+]
+
+[package.dependencies]
+idna = ">=2.8"
+sniffio = ">=1.1"
+
+[package.extras]
+trio = ["trio (>=0.31.0)"]
+
+[[package]]
+name = "appnope"
+version = "0.1.4"
+description = "Disable App Nap on macOS >= 10.9"
+optional = false
+python-versions = ">=3.6"
+groups = ["main", "dev"]
+markers = "sys_platform == \"darwin\""
+files = [
+ {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"},
+ {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"},
+]
+
+[[package]]
+name = "attrs"
+version = "25.4.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"},
+ {file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"},
+]
+
+[[package]]
+name = "babel"
+version = "2.17.0"
+description = "Internationalization utilities"
+optional = false
+python-versions = ">=3.8"
+groups = ["docs"]
+files = [
+ {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"},
+ {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"},
+]
+
+[package.extras]
+dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""]
+
+[[package]]
+name = "backcall"
+version = "0.2.0"
+description = "Specifications for callback functions passed in to an API"
+optional = false
+python-versions = "*"
+groups = ["main", "dev"]
+files = [
+ {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
+ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
+]
+
+[[package]]
+name = "beautifulsoup4"
+version = "4.13.3"
+description = "Screen-scraping library"
+optional = false
+python-versions = ">=3.7.0"
+groups = ["main", "dev"]
+files = [
+ {file = "beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16"},
+ {file = "beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b"},
+]
+
+[package.dependencies]
+soupsieve = ">1.2"
+typing-extensions = ">=4.0.0"
+
+[package.extras]
+cchardet = ["cchardet"]
+chardet = ["chardet"]
+charset-normalizer = ["charset-normalizer"]
+html5lib = ["html5lib"]
+lxml = ["lxml"]
+
+[[package]]
+name = "billiard"
+version = "4.2.2"
+description = "Python multiprocessing fork with improvements and bugfixes"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "billiard-4.2.2-py3-none-any.whl", hash = "sha256:4bc05dcf0d1cc6addef470723aac2a6232f3c7ed7475b0b580473a9145829457"},
+ {file = "billiard-4.2.2.tar.gz", hash = "sha256:e815017a062b714958463e07ba15981d802dc53d41c5b69d28c5a7c238f8ecf3"},
+]
+
+[[package]]
+name = "black"
+version = "25.9.0"
+description = "The uncompromising code formatter."
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "black-25.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ce41ed2614b706fd55fd0b4a6909d06b5bab344ffbfadc6ef34ae50adba3d4f7"},
+ {file = "black-25.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ab0ce111ef026790e9b13bd216fa7bc48edd934ffc4cbf78808b235793cbc92"},
+ {file = "black-25.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f96b6726d690c96c60ba682955199f8c39abc1ae0c3a494a9c62c0184049a713"},
+ {file = "black-25.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:d119957b37cc641596063cd7db2656c5be3752ac17877017b2ffcdb9dfc4d2b1"},
+ {file = "black-25.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:456386fe87bad41b806d53c062e2974615825c7a52159cde7ccaeb0695fa28fa"},
+ {file = "black-25.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a16b14a44c1af60a210d8da28e108e13e75a284bf21a9afa6b4571f96ab8bb9d"},
+ {file = "black-25.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aaf319612536d502fdd0e88ce52d8f1352b2c0a955cc2798f79eeca9d3af0608"},
+ {file = "black-25.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:c0372a93e16b3954208417bfe448e09b0de5cc721d521866cd9e0acac3c04a1f"},
+ {file = "black-25.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1b9dc70c21ef8b43248f1d86aedd2aaf75ae110b958a7909ad8463c4aa0880b0"},
+ {file = "black-25.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e46eecf65a095fa62e53245ae2795c90bdecabd53b50c448d0a8bcd0d2e74c4"},
+ {file = "black-25.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9101ee58ddc2442199a25cb648d46ba22cd580b00ca4b44234a324e3ec7a0f7e"},
+ {file = "black-25.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:77e7060a00c5ec4b3367c55f39cf9b06e68965a4f2e61cecacd6d0d9b7ec945a"},
+ {file = "black-25.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0172a012f725b792c358d57fe7b6b6e8e67375dd157f64fa7a3097b3ed3e2175"},
+ {file = "black-25.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3bec74ee60f8dfef564b573a96b8930f7b6a538e846123d5ad77ba14a8d7a64f"},
+ {file = "black-25.9.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b756fc75871cb1bcac5499552d771822fd9db5a2bb8db2a7247936ca48f39831"},
+ {file = "black-25.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:846d58e3ce7879ec1ffe816bb9df6d006cd9590515ed5d17db14e17666b2b357"},
+ {file = "black-25.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef69351df3c84485a8beb6f7b8f9721e2009e20ef80a8d619e2d1788b7816d47"},
+ {file = "black-25.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e3c1f4cd5e93842774d9ee4ef6cd8d17790e65f44f7cdbaab5f2cf8ccf22a823"},
+ {file = "black-25.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:154b06d618233fe468236ba1f0e40823d4eb08b26f5e9261526fde34916b9140"},
+ {file = "black-25.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:e593466de7b998374ea2585a471ba90553283fb9beefcfa430d84a2651ed5933"},
+ {file = "black-25.9.0-py3-none-any.whl", hash = "sha256:474b34c1342cdc157d307b56c4c65bce916480c4a8f6551fdc6bf9b486a7c4ae"},
+ {file = "black-25.9.0.tar.gz", hash = "sha256:0474bca9a0dd1b51791fcc507a4e02078a1c63f6d4e4ae5544b9848c7adfb619"},
+]
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+packaging = ">=22.0"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+pytokens = ">=0.1.10"
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.10)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "bleach"
+version = "6.2.0"
+description = "An easy safelist-based HTML-sanitizing tool."
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "bleach-6.2.0-py3-none-any.whl", hash = "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e"},
+ {file = "bleach-6.2.0.tar.gz", hash = "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f"},
+]
+
+[package.dependencies]
+tinycss2 = {version = ">=1.1.0,<1.5", optional = true, markers = "extra == \"css\""}
+webencodings = "*"
+
+[package.extras]
+css = ["tinycss2 (>=1.1.0,<1.5)"]
+
+[[package]]
+name = "boto3"
+version = "1.40.18"
+description = "The AWS SDK for Python"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "boto3-1.40.18-py3-none-any.whl", hash = "sha256:daa776ba1251a7458c9d6c7627873d0c2460c8e8272d35759065580e9193700a"},
+ {file = "boto3-1.40.18.tar.gz", hash = "sha256:64301d39adecc154e3e595eaf0d4f28998ef0a5551f1d033aeac51a9e1a688e5"},
+]
+
+[package.dependencies]
+botocore = ">=1.40.18,<1.41.0"
+jmespath = ">=0.7.1,<2.0.0"
+s3transfer = ">=0.13.0,<0.14.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
+
+[[package]]
+name = "botocore"
+version = "1.40.18"
+description = "Low-level, data-driven core of boto 3."
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "botocore-1.40.18-py3-none-any.whl", hash = "sha256:57025c46ca00cf8cec25de07a759521bfbfb3036a0f69b272654a354615dc45f"},
+ {file = "botocore-1.40.18.tar.gz", hash = "sha256:afd69bdadd8c55cc89d69de0799829e555193a352d87867f746e19020271cc0f"},
+]
+
+[package.dependencies]
+jmespath = ">=0.7.1,<2.0.0"
+python-dateutil = ">=2.1,<3.0.0"
+urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}
+
+[package.extras]
+crt = ["awscrt (==0.27.6)"]
+
+[[package]]
+name = "cachetools"
+version = "5.5.2"
+description = "Extensible memoizing collections and decorators"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"},
+ {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"},
+]
+
+[[package]]
+name = "celery"
+version = "5.5.0"
+description = "Distributed Task Queue."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "celery-5.5.0-py3-none-any.whl", hash = "sha256:f4170c6e5952281318448a899d9e9a15b9cbd007e002091766900dc8f71b9394"},
+ {file = "celery-5.5.0.tar.gz", hash = "sha256:10d49f9926d16237310109b0e6e1e2f7a2133b84e684bb36534d7663e66919bb"},
+]
+
+[package.dependencies]
+billiard = ">=4.2.1,<5.0"
+click = ">=8.1.2,<9.0"
+click-didyoumean = ">=0.3.0"
+click-plugins = ">=1.1.1"
+click-repl = ">=0.2.0"
+kombu = ">=5.5.2,<5.6"
+python-dateutil = ">=2.8.2"
+vine = ">=5.1.0,<6.0"
+
+[package.extras]
+arangodb = ["pyArango (>=2.0.2)"]
+auth = ["cryptography (==44.0.2)"]
+azureblockblob = ["azure-identity (>=1.19.0)", "azure-storage-blob (>=12.15.0)"]
+brotli = ["brotli (>=1.0.0) ; platform_python_implementation == \"CPython\"", "brotlipy (>=0.7.0) ; platform_python_implementation == \"PyPy\""]
+cassandra = ["cassandra-driver (>=3.25.0,<4)"]
+consul = ["python-consul2 (==0.1.5)"]
+cosmosdbsql = ["pydocumentdb (==2.3.5)"]
+couchbase = ["couchbase (>=3.0.0) ; platform_python_implementation != \"PyPy\" and (platform_system != \"Windows\" or python_version < \"3.10\")"]
+couchdb = ["pycouchdb (==1.16.0)"]
+django = ["Django (>=2.2.28)"]
+dynamodb = ["boto3 (>=1.26.143)"]
+elasticsearch = ["elastic-transport (<=8.17.1)", "elasticsearch (<=8.17.2)"]
+eventlet = ["eventlet (>=0.32.0) ; python_version < \"3.10\""]
+gcs = ["google-cloud-firestore (==2.20.1)", "google-cloud-storage (>=2.10.0)", "grpcio (==1.67.0)"]
+gevent = ["gevent (>=1.5.0)"]
+librabbitmq = ["librabbitmq (>=2.0.0) ; python_version < \"3.11\""]
+memcache = ["pylibmc (==1.6.3) ; platform_system != \"Windows\""]
+mongodb = ["pymongo (==4.10.1)"]
+msgpack = ["msgpack (==1.1.0)"]
+pydantic = ["pydantic (>=2.4)"]
+pymemcache = ["python-memcached (>=1.61)"]
+pyro = ["pyro4 (==4.82) ; python_version < \"3.11\""]
+pytest = ["pytest-celery[all] (>=1.2.0,<1.3.0)"]
+redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"]
+s3 = ["boto3 (>=1.26.143)"]
+slmq = ["softlayer_messaging (>=1.0.3)"]
+solar = ["ephem (==4.2) ; platform_python_implementation != \"PyPy\""]
+sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"]
+sqs = ["boto3 (>=1.26.143)", "kombu[sqs] (>=5.3.4)", "urllib3 (>=1.26.16)"]
+tblib = ["tblib (>=1.3.0) ; python_version < \"3.8.0\"", "tblib (>=1.5.0) ; python_version >= \"3.8.0\""]
+yaml = ["PyYAML (>=3.10)"]
+zookeeper = ["kazoo (>=1.3.1)"]
+zstd = ["zstandard (==0.23.0)"]
+
+[[package]]
+name = "celery-amqp-backend"
+version = "1.2.0"
+description = "A rewrite of the original Celery AMQP result backend that supports Celery 5.0 and newer."
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "celery_amqp_backend-1.2.0-py3-none-any.whl", hash = "sha256:4b106251dfbd9060739ba22dd5caefe7fd0cc72bd06956056d850e2bb77374fc"},
+ {file = "celery_amqp_backend-1.2.0.tar.gz", hash = "sha256:b4a4788d52ee710d02498fad1283a03dcd64fcd1966daa28c14b76ecb71d478d"},
+]
+
+[package.dependencies]
+celery = ">=5.2,<6.0"
+
+[[package]]
+name = "certifi"
+version = "2025.1.31"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+groups = ["main", "dev", "docs"]
+files = [
+ {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"},
+ {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"},
+]
+
+[[package]]
+name = "cffi"
+version = "2.0.0"
+description = "Foreign Function Interface for Python calling C code."
+optional = false
+python-versions = ">=3.9"
+groups = ["main", "dev"]
+files = [
+ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"},
+ {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"},
+ {file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"},
+ {file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"},
+ {file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"},
+ {file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"},
+ {file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"},
+ {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"},
+ {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"},
+ {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"},
+ {file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"},
+ {file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"},
+ {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"},
+ {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"},
+ {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"},
+ {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"},
+ {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"},
+ {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"},
+ {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"},
+ {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"},
+ {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"},
+ {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"},
+ {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"},
+ {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"},
+ {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"},
+ {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"},
+ {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"},
+ {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"},
+ {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"},
+ {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"},
+ {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"},
+ {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"},
+ {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"},
+ {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"},
+ {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"},
+ {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"},
+ {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"},
+ {file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"},
+ {file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"},
+ {file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"},
+ {file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"},
+ {file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"},
+ {file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"},
+ {file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"},
+ {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"},
+ {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"},
+ {file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"},
+ {file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"},
+ {file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"},
+ {file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"},
+ {file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"},
+ {file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"},
+ {file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"},
+ {file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"},
+ {file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"},
+ {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"},
+ {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"},
+ {file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"},
+ {file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"},
+ {file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"},
+ {file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"},
+ {file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"},
+ {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"},
+ {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"},
+ {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"},
+ {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"},
+ {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"},
+ {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"},
+ {file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"},
+ {file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"},
+ {file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"},
+ {file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"},
+ {file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"},
+ {file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"},
+ {file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"},
+ {file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"},
+ {file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"},
+ {file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"},
+ {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"},
+ {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"},
+ {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"},
+ {file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"},
+ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"},
+ {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"},
+]
+markers = {main = "implementation_name == \"pypy\" or platform_python_implementation != \"PyPy\"", dev = "implementation_name == \"pypy\""}
+
+[package.dependencies]
+pycparser = {version = "*", markers = "implementation_name != \"PyPy\""}
+
+[[package]]
+name = "chardet"
+version = "5.2.0"
+description = "Universal encoding detector for Python 3"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"},
+ {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.4.3"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7"
+groups = ["dev", "docs"]
+files = [
+ {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"},
+ {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"},
+ {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"},
+ {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"},
+ {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"},
+ {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"},
+ {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"},
+ {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"},
+ {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"},
+ {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"},
+]
+
+[[package]]
+name = "click"
+version = "8.3.0"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.10"
+groups = ["main", "docs"]
+files = [
+ {file = "click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc"},
+ {file = "click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "click-didyoumean"
+version = "0.3.1"
+description = "Enables git-like *did-you-mean* feature in click"
+optional = false
+python-versions = ">=3.6.2"
+groups = ["main"]
+files = [
+ {file = "click_didyoumean-0.3.1-py3-none-any.whl", hash = "sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c"},
+ {file = "click_didyoumean-0.3.1.tar.gz", hash = "sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463"},
+]
+
+[package.dependencies]
+click = ">=7"
+
+[[package]]
+name = "click-plugins"
+version = "1.1.1.2"
+description = "An extension module for click to enable registering CLI commands via setuptools entry-points."
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "click_plugins-1.1.1.2-py2.py3-none-any.whl", hash = "sha256:008d65743833ffc1f5417bf0e78e8d2c23aab04d9745ba817bd3e71b0feb6aa6"},
+ {file = "click_plugins-1.1.1.2.tar.gz", hash = "sha256:d7af3984a99d243c131aa1a828331e7630f4a88a9741fd05c927b204bcf92261"},
+]
+
+[package.dependencies]
+click = ">=4.0"
+
+[package.extras]
+dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"]
+
+[[package]]
+name = "click-repl"
+version = "0.3.0"
+description = "REPL plugin for Click"
+optional = false
+python-versions = ">=3.6"
+groups = ["main"]
+files = [
+ {file = "click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9"},
+ {file = "click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+prompt-toolkit = ">=3.0.36"
+
+[package.extras]
+testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+groups = ["main", "dev", "docs"]
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+markers = {main = "sys_platform == \"win32\" or platform_system == \"Windows\"", dev = "sys_platform == \"win32\""}
+
+[[package]]
+name = "colorlog"
+version = "6.9.0"
+description = "Add colours to the output of Python's logging module."
+optional = false
+python-versions = ">=3.6"
+groups = ["dev"]
+files = [
+ {file = "colorlog-6.9.0-py3-none-any.whl", hash = "sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff"},
+ {file = "colorlog-6.9.0.tar.gz", hash = "sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+development = ["black", "flake8", "mypy", "pytest", "types-colorama"]
+
+[[package]]
+name = "coverage"
+version = "6.5.0"
+description = "Code coverage measurement for Python"
+optional = false
+python-versions = ">=3.7"
+groups = ["dev"]
+files = [
+ {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"},
+ {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"},
+ {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"},
+ {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"},
+ {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"},
+ {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"},
+ {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"},
+ {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"},
+ {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"},
+ {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"},
+ {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"},
+ {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"},
+ {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"},
+ {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"},
+ {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"},
+ {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"},
+ {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"},
+ {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"},
+ {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"},
+ {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"},
+]
+
+[package.extras]
+toml = ["tomli ; python_full_version <= \"3.11.0a6\""]
+
+[[package]]
+name = "coveralls"
+version = "3.3.1"
+description = "Show coverage stats online via coveralls.io"
+optional = false
+python-versions = ">= 3.5"
+groups = ["dev"]
+files = [
+ {file = "coveralls-3.3.1-py2.py3-none-any.whl", hash = "sha256:f42015f31d386b351d4226389b387ae173207058832fbf5c8ec4b40e27b16026"},
+ {file = "coveralls-3.3.1.tar.gz", hash = "sha256:b32a8bb5d2df585207c119d6c01567b81fba690c9c10a753bfe27a335bfc43ea"},
+]
+
+[package.dependencies]
+coverage = ">=4.1,<6.0.dev0 || >6.1,<6.1.1 || >6.1.1,<7.0"
+docopt = ">=0.6.1"
+requests = ">=1.0.0"
+
+[package.extras]
+yaml = ["PyYAML (>=3.10)"]
+
+[[package]]
+name = "cryptography"
+version = "44.0.2"
+description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
+optional = false
+python-versions = "!=3.9.0,!=3.9.1,>=3.7"
+groups = ["main"]
+files = [
+ {file = "cryptography-44.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7"},
+ {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1"},
+ {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb"},
+ {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843"},
+ {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5"},
+ {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c"},
+ {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a"},
+ {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308"},
+ {file = "cryptography-44.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688"},
+ {file = "cryptography-44.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7"},
+ {file = "cryptography-44.0.2-cp37-abi3-win32.whl", hash = "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79"},
+ {file = "cryptography-44.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa"},
+ {file = "cryptography-44.0.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3"},
+ {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639"},
+ {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd"},
+ {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181"},
+ {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea"},
+ {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699"},
+ {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9"},
+ {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23"},
+ {file = "cryptography-44.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922"},
+ {file = "cryptography-44.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4"},
+ {file = "cryptography-44.0.2-cp39-abi3-win32.whl", hash = "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5"},
+ {file = "cryptography-44.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6"},
+ {file = "cryptography-44.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb"},
+ {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41"},
+ {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562"},
+ {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5"},
+ {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa"},
+ {file = "cryptography-44.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d"},
+ {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d"},
+ {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471"},
+ {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615"},
+ {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390"},
+ {file = "cryptography-44.0.2.tar.gz", hash = "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0"},
+]
+
+[package.dependencies]
+cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
+
+[package.extras]
+docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""]
+docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"]
+nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""]
+pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
+sdist = ["build (>=1.0.0)"]
+ssh = ["bcrypt (>=3.1.5)"]
+test = ["certifi (>=2024)", "cryptography-vectors (==44.0.2)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
+test-randomorder = ["pytest-randomly"]
+
+[[package]]
+name = "decorator"
+version = "5.2.1"
+description = "Decorators for Humans"
+optional = false
+python-versions = ">=3.8"
+groups = ["main", "dev"]
+files = [
+ {file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"},
+ {file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"},
+]
+
+[[package]]
+name = "defusedxml"
+version = "0.7.1"
+description = "XML bomb protection for Python stdlib modules"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+groups = ["main"]
+files = [
+ {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
+ {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"},
+]
+
+[[package]]
+name = "docopt"
+version = "0.6.2"
+description = "Pythonic argument parser, that will make you smile"
+optional = false
+python-versions = "*"
+groups = ["main", "dev"]
+files = [
+ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"},
+]
+
+[[package]]
+name = "docutils"
+version = "0.21.2"
+description = "Docutils -- Python Documentation Utilities"
+optional = false
+python-versions = ">=3.9"
+groups = ["main", "docs"]
+files = [
+ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"},
+ {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"},
+]
+
+[[package]]
+name = "et-xmlfile"
+version = "2.0.0"
+description = "An implementation of lxml.xmlfile for the standard library"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa"},
+ {file = "et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"},
+]
+
+[[package]]
+name = "fastjsonschema"
+version = "2.21.2"
+description = "Fastest Python implementation of JSON schema"
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"},
+ {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"},
+]
+
+[package.extras]
+devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"]
+
+[[package]]
+name = "flake8"
+version = "7.1.2"
+description = "the modular source code checker: pep8 pyflakes and co"
+optional = false
+python-versions = ">=3.8.1"
+groups = ["dev"]
+files = [
+ {file = "flake8-7.1.2-py2.py3-none-any.whl", hash = "sha256:1cbc62e65536f65e6d754dfe6f1bada7f5cf392d6f5db3c2b85892466c3e7c1a"},
+ {file = "flake8-7.1.2.tar.gz", hash = "sha256:c586ffd0b41540951ae41af572e6790dbd49fc12b3aa2541685d253d9bd504bd"},
+]
+
+[package.dependencies]
+mccabe = ">=0.7.0,<0.8.0"
+pycodestyle = ">=2.12.0,<2.13.0"
+pyflakes = ">=3.2.0,<3.3.0"
+
+[[package]]
+name = "frozenlist"
+version = "1.8.0"
+description = "A list-like structure which implements collections.abc.MutableSequence"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011"},
+ {file = "frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565"},
+ {file = "frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad"},
+ {file = "frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2"},
+ {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186"},
+ {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e"},
+ {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450"},
+ {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef"},
+ {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4"},
+ {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff"},
+ {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c"},
+ {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f"},
+ {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7"},
+ {file = "frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a"},
+ {file = "frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6"},
+ {file = "frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e"},
+ {file = "frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84"},
+ {file = "frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9"},
+ {file = "frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93"},
+ {file = "frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f"},
+ {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695"},
+ {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52"},
+ {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581"},
+ {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567"},
+ {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b"},
+ {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92"},
+ {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d"},
+ {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd"},
+ {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967"},
+ {file = "frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25"},
+ {file = "frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b"},
+ {file = "frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a"},
+ {file = "frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1"},
+ {file = "frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b"},
+ {file = "frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4"},
+ {file = "frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383"},
+ {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4"},
+ {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8"},
+ {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b"},
+ {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52"},
+ {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29"},
+ {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3"},
+ {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143"},
+ {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608"},
+ {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa"},
+ {file = "frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf"},
+ {file = "frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746"},
+ {file = "frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd"},
+ {file = "frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a"},
+ {file = "frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7"},
+ {file = "frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40"},
+ {file = "frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027"},
+ {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822"},
+ {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121"},
+ {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5"},
+ {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e"},
+ {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11"},
+ {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1"},
+ {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1"},
+ {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8"},
+ {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed"},
+ {file = "frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496"},
+ {file = "frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231"},
+ {file = "frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888"},
+ {file = "frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042"},
+ {file = "frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0"},
+ {file = "frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f"},
+ {file = "frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c"},
+ {file = "frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2"},
+ {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8"},
+ {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686"},
+ {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e"},
+ {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a"},
+ {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128"},
+ {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f"},
+ {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7"},
+ {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30"},
+ {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7"},
+ {file = "frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806"},
+ {file = "frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0"},
+ {file = "frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd"},
+ {file = "frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79"},
+ {file = "frozenlist-1.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47"},
+ {file = "frozenlist-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca"},
+ {file = "frozenlist-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068"},
+ {file = "frozenlist-1.8.0-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95"},
+ {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459"},
+ {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675"},
+ {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61"},
+ {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6"},
+ {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5"},
+ {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3"},
+ {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1"},
+ {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178"},
+ {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda"},
+ {file = "frozenlist-1.8.0-cp39-cp39-win32.whl", hash = "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087"},
+ {file = "frozenlist-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a"},
+ {file = "frozenlist-1.8.0-cp39-cp39-win_arm64.whl", hash = "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103"},
+ {file = "frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d"},
+ {file = "frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad"},
+]
+
+[[package]]
+name = "furl"
+version = "2.0.0"
+description = "URL manipulation made simple."
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "furl-2.0.0-py2.py3-none-any.whl", hash = "sha256:f7e90e9f85ef3f2e64485f04c2a80b50af6133942812fd87a44d45305b079018"},
+ {file = "furl-2.0.0.tar.gz", hash = "sha256:fdcaedc1fb19a63d7d875b0105b0a5b496dd0989330d454a42bcb401fa5454ec"},
+]
+
+[package.dependencies]
+orderedmultidict = ">=1.0"
+six = ">=1.8.0"
+
+[[package]]
+name = "google-auth"
+version = "2.38.0"
+description = "Google Authentication Library"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "google_auth-2.38.0-py2.py3-none-any.whl", hash = "sha256:e7dae6694313f434a2727bf2906f27ad259bae090d7aa896590d86feec3d9d4a"},
+ {file = "google_auth-2.38.0.tar.gz", hash = "sha256:8285113607d3b80a3f1543b75962447ba8a09fe85783432a784fdeef6ac094c4"},
+]
+
+[package.dependencies]
+cachetools = ">=2.0.0,<6.0"
+pyasn1-modules = ">=0.2.1"
+rsa = ">=3.1.4,<5"
+
+[package.extras]
+aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"]
+enterprise-cert = ["cryptography", "pyopenssl"]
+pyjwt = ["cryptography (>=38.0.3)", "pyjwt (>=2.0)"]
+pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"]
+reauth = ["pyu2f (>=0.1.5)"]
+requests = ["requests (>=2.20.0,<3.0.0.dev0)"]
+
+[[package]]
+name = "h11"
+version = "0.16.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+optional = false
+python-versions = ">=3.8"
+groups = ["docs"]
+files = [
+ {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"},
+ {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"},
+]
+
+[[package]]
+name = "h5py"
+version = "3.13.0"
+description = "Read and write HDF5 files from Python"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "h5py-3.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5540daee2b236d9569c950b417f13fd112d51d78b4c43012de05774908dff3f5"},
+ {file = "h5py-3.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:10894c55d46df502d82a7a4ed38f9c3fdbcb93efb42e25d275193e093071fade"},
+ {file = "h5py-3.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb267ce4b83f9c42560e9ff4d30f60f7ae492eacf9c7ede849edf8c1b860e16b"},
+ {file = "h5py-3.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2cf6a231a07c14acd504a945a6e9ec115e0007f675bde5e0de30a4dc8d86a31"},
+ {file = "h5py-3.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:851ae3a8563d87a5a0dc49c2e2529c75b8842582ccaefbf84297d2cfceeacd61"},
+ {file = "h5py-3.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8a8e38ef4ceb969f832cc230c0cf808c613cc47e31e768fd7b1106c55afa1cb8"},
+ {file = "h5py-3.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f35640e81b03c02a88b8bf99fb6a9d3023cc52f7c627694db2f379e0028f2868"},
+ {file = "h5py-3.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:337af114616f3656da0c83b68fcf53ecd9ce9989a700b0883a6e7c483c3235d4"},
+ {file = "h5py-3.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:782ff0ac39f455f21fd1c8ebc007328f65f43d56718a89327eec76677ebf238a"},
+ {file = "h5py-3.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:22ffe2a25770a2d67213a1b94f58006c14dce06933a42d2aaa0318c5868d1508"},
+ {file = "h5py-3.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:477c58307b6b9a2509c59c57811afb9f598aedede24a67da808262dfa0ee37b4"},
+ {file = "h5py-3.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:57c4c74f627c616f02b7aec608a8c706fe08cb5b0ba7c08555a4eb1dde20805a"},
+ {file = "h5py-3.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:357e6dc20b101a805ccfd0024731fbaf6e8718c18c09baf3b5e4e9d198d13fca"},
+ {file = "h5py-3.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6f13f9b5ce549448c01e4dfe08ea8d1772e6078799af2c1c8d09e941230a90d"},
+ {file = "h5py-3.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:21daf38171753899b5905f3d82c99b0b1ec2cbbe282a037cad431feb620e62ec"},
+ {file = "h5py-3.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e520ec76de00943dd017c8ea3f354fa1d2f542eac994811943a8faedf2a7d5cb"},
+ {file = "h5py-3.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e79d8368cd9295045956bfb436656bea3f915beaa11d342e9f79f129f5178763"},
+ {file = "h5py-3.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56dd172d862e850823c4af02dc4ddbc308f042b85472ffdaca67f1598dff4a57"},
+ {file = "h5py-3.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be949b46b7388074c5acae017fbbe3e5ba303fd9daaa52157fdfef30bbdacadd"},
+ {file = "h5py-3.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:4f97ecde7ac6513b21cd95efdfc38dc6d19f96f6ca6f2a30550e94e551458e0a"},
+ {file = "h5py-3.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82690e89c72b85addf4fc4d5058fb1e387b6c14eb063b0b879bf3f42c3b93c35"},
+ {file = "h5py-3.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d571644958c5e19a61c793d8d23cd02479572da828e333498c9acc463f4a3997"},
+ {file = "h5py-3.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:560e71220dc92dfa254b10a4dcb12d56b574d2d87e095db20466b32a93fec3f9"},
+ {file = "h5py-3.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c10f061764d8dce0a9592ce08bfd5f243a00703325c388f1086037e5d619c5f1"},
+ {file = "h5py-3.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:9c82ece71ed1c2b807b6628e3933bc6eae57ea21dac207dca3470e3ceaaf437c"},
+ {file = "h5py-3.13.0.tar.gz", hash = "sha256:1870e46518720023da85d0895a1960ff2ce398c5671eac3b1a41ec696b7105c3"},
+]
+
+[package.dependencies]
+numpy = ">=1.19.3"
+
+[[package]]
+name = "humanfriendly"
+version = "10.0"
+description = "Human friendly output for text interfaces using Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+groups = ["main"]
+files = [
+ {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"},
+ {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"},
+]
+
+[package.dependencies]
+pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""}
+
+[[package]]
+name = "idna"
+version = "3.10"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.6"
+groups = ["main", "dev", "docs"]
+files = [
+ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
+ {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
+]
+
+[package.extras]
+all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
+
+[[package]]
+name = "imageio"
+version = "2.37.0"
+description = "Library for reading and writing a wide range of image, video, scientific, and volumetric data formats."
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "imageio-2.37.0-py3-none-any.whl", hash = "sha256:11efa15b87bc7871b61590326b2d635439acc321cf7f8ce996f812543ce10eed"},
+ {file = "imageio-2.37.0.tar.gz", hash = "sha256:71b57b3669666272c818497aebba2b4c5f20d5b37c81720e5e1a56d59c492996"},
+]
+
+[package.dependencies]
+numpy = "*"
+pillow = ">=8.3.2"
+
+[package.extras]
+all-plugins = ["astropy", "av", "imageio-ffmpeg", "numpy (>2)", "pillow-heif", "psutil", "rawpy", "tifffile"]
+all-plugins-pypy = ["av", "imageio-ffmpeg", "pillow-heif", "psutil", "tifffile"]
+build = ["wheel"]
+dev = ["black", "flake8", "fsspec[github]", "pytest", "pytest-cov"]
+docs = ["numpydoc", "pydata-sphinx-theme", "sphinx (<6)"]
+ffmpeg = ["imageio-ffmpeg", "psutil"]
+fits = ["astropy"]
+full = ["astropy", "av", "black", "flake8", "fsspec[github]", "gdal", "imageio-ffmpeg", "itk", "numpy (>2)", "numpydoc", "pillow-heif", "psutil", "pydata-sphinx-theme", "pytest", "pytest-cov", "rawpy", "sphinx (<6)", "tifffile", "wheel"]
+gdal = ["gdal"]
+itk = ["itk"]
+linting = ["black", "flake8"]
+pillow-heif = ["pillow-heif"]
+pyav = ["av"]
+rawpy = ["numpy (>2)", "rawpy"]
+test = ["fsspec[github]", "pytest", "pytest-cov"]
+tifffile = ["tifffile"]
+
+[[package]]
+name = "imagesize"
+version = "1.4.1"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+groups = ["docs"]
+files = [
+ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
+ {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.1.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.8"
+groups = ["dev"]
+files = [
+ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"},
+ {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"},
+]
+
+[[package]]
+name = "invoke"
+version = "2.2.0"
+description = "Pythonic task execution"
+optional = false
+python-versions = ">=3.6"
+groups = ["main"]
+files = [
+ {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"},
+ {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"},
+]
+
+[[package]]
+name = "ipdb"
+version = "0.13.13"
+description = "IPython-enabled pdb"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+groups = ["dev"]
+files = [
+ {file = "ipdb-0.13.13-py3-none-any.whl", hash = "sha256:45529994741c4ab6d2388bfa5d7b725c2cf7fe9deffabdb8a6113aa5ed449ed4"},
+ {file = "ipdb-0.13.13.tar.gz", hash = "sha256:e3ac6018ef05126d442af680aad863006ec19d02290561ac88b8b1c0b0cfc726"},
+]
+
+[package.dependencies]
+decorator = {version = "*", markers = "python_version >= \"3.11\""}
+ipython = {version = ">=7.31.1", markers = "python_version >= \"3.11\""}
+
+[[package]]
+name = "ipython"
+version = "7.31.1"
+description = "IPython: Productive Interactive Computing"
+optional = false
+python-versions = ">=3.7"
+groups = ["main", "dev"]
+files = [
+ {file = "ipython-7.31.1-py3-none-any.whl", hash = "sha256:55df3e0bd0f94e715abd968bedd89d4e8a7bce4bf498fb123fed4f5398fea874"},
+ {file = "ipython-7.31.1.tar.gz", hash = "sha256:b5548ec5329a4bcf054a5deed5099b0f9622eb9ea51aaa7104d215fece201d8c"},
+]
+
+[package.dependencies]
+appnope = {version = "*", markers = "sys_platform == \"darwin\""}
+backcall = "*"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+decorator = "*"
+jedi = ">=0.16"
+matplotlib-inline = "*"
+pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
+pickleshare = "*"
+prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0"
+pygments = "*"
+setuptools = ">=18.5"
+traitlets = ">=4.2"
+
+[package.extras]
+all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"]
+doc = ["Sphinx (>=1.3)"]
+kernel = ["ipykernel"]
+nbconvert = ["nbconvert"]
+nbformat = ["nbformat"]
+notebook = ["ipywidgets", "notebook"]
+parallel = ["ipyparallel"]
+qtconsole = ["qtconsole"]
+test = ["ipykernel", "nbformat", "nose (>=0.10.1)", "numpy (>=1.17)", "pygments", "requests", "testpath"]
+
+[[package]]
+name = "isort"
+version = "6.1.0"
+description = "A Python utility / library to sort Python imports."
+optional = false
+python-versions = ">=3.9.0"
+groups = ["main"]
+files = [
+ {file = "isort-6.1.0-py3-none-any.whl", hash = "sha256:58d8927ecce74e5087aef019f778d4081a3b6c98f15a80ba35782ca8a2097784"},
+ {file = "isort-6.1.0.tar.gz", hash = "sha256:9b8f96a14cfee0677e78e941ff62f03769a06d412aabb9e2a90487b3b7e8d481"},
+]
+
+[package.extras]
+colors = ["colorama"]
+plugins = ["setuptools"]
+
+[[package]]
+name = "jedi"
+version = "0.19.2"
+description = "An autocompletion tool for Python that can be used for text editors."
+optional = false
+python-versions = ">=3.6"
+groups = ["main", "dev"]
+files = [
+ {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"},
+ {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"},
+]
+
+[package.dependencies]
+parso = ">=0.8.4,<0.9.0"
+
+[package.extras]
+docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
+qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
+testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"]
+
+[[package]]
+name = "jinja2"
+version = "3.1.5"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+groups = ["main", "docs"]
+files = [
+ {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"},
+ {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "jmespath"
+version = "1.0.1"
+description = "JSON Matching Expressions"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
+ {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
+]
+
+[[package]]
+name = "jsonschema"
+version = "4.24.0"
+description = "An implementation of JSON Schema validation for Python"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "jsonschema-4.24.0-py3-none-any.whl", hash = "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d"},
+ {file = "jsonschema-4.24.0.tar.gz", hash = "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+jsonschema-specifications = ">=2023.03.6"
+referencing = ">=0.28.4"
+rpds-py = ">=0.7.1"
+
+[package.extras]
+format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
+format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"]
+
+[[package]]
+name = "jsonschema-specifications"
+version = "2025.9.1"
+description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"},
+ {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"},
+]
+
+[package.dependencies]
+referencing = ">=0.31.0"
+
+[[package]]
+name = "jupyter-client"
+version = "8.6.3"
+description = "Jupyter protocol implementation and client libraries"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f"},
+ {file = "jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419"},
+]
+
+[package.dependencies]
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
+python-dateutil = ">=2.8.2"
+pyzmq = ">=23.0"
+tornado = ">=6.2"
+traitlets = ">=5.3"
+
+[package.extras]
+docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"]
+test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko ; sys_platform == \"win32\"", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"]
+
+[[package]]
+name = "jupyter-core"
+version = "5.8.1"
+description = "Jupyter core package. A base package on which Jupyter projects rely."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "jupyter_core-5.8.1-py3-none-any.whl", hash = "sha256:c28d268fc90fb53f1338ded2eb410704c5449a358406e8a948b75706e24863d0"},
+ {file = "jupyter_core-5.8.1.tar.gz", hash = "sha256:0a5f9706f70e64786b75acba995988915ebd4601c8a52e534a40b51c95f59941"},
+]
+
+[package.dependencies]
+platformdirs = ">=2.5"
+pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""}
+traitlets = ">=5.3"
+
+[package.extras]
+docs = ["intersphinx-registry", "myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-spelling", "traitlets"]
+test = ["ipykernel", "pre-commit", "pytest (<9)", "pytest-cov", "pytest-timeout"]
+
+[[package]]
+name = "jupyterlab-pygments"
+version = "0.3.0"
+description = "Pygments theme using JupyterLab CSS variables"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"},
+ {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"},
+]
+
+[[package]]
+name = "kombu"
+version = "5.5.4"
+description = "Messaging library for Python."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "kombu-5.5.4-py3-none-any.whl", hash = "sha256:a12ed0557c238897d8e518f1d1fdf84bd1516c5e305af2dacd85c2015115feb8"},
+ {file = "kombu-5.5.4.tar.gz", hash = "sha256:886600168275ebeada93b888e831352fe578168342f0d1d5833d88ba0d847363"},
+]
+
+[package.dependencies]
+amqp = ">=5.1.1,<6.0.0"
+packaging = "*"
+tzdata = {version = ">=2025.2", markers = "python_version >= \"3.9\""}
+vine = "5.1.0"
+
+[package.extras]
+azureservicebus = ["azure-servicebus (>=7.10.0)"]
+azurestoragequeues = ["azure-identity (>=1.12.0)", "azure-storage-queue (>=12.6.0)"]
+confluentkafka = ["confluent-kafka (>=2.2.0)"]
+consul = ["python-consul2 (==0.1.5)"]
+gcpubsub = ["google-cloud-monitoring (>=2.16.0)", "google-cloud-pubsub (>=2.18.4)", "grpcio (==1.67.0)", "protobuf (==4.25.5)"]
+librabbitmq = ["librabbitmq (>=2.0.0) ; python_version < \"3.11\""]
+mongodb = ["pymongo (==4.10.1)"]
+msgpack = ["msgpack (==1.1.0)"]
+pyro = ["pyro4 (==4.82)"]
+qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"]
+redis = ["redis (>=4.5.2,!=4.5.5,!=5.0.2,<=5.2.1)"]
+slmq = ["softlayer_messaging (>=1.0.3)"]
+sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"]
+sqs = ["boto3 (>=1.26.143)", "urllib3 (>=1.26.16)"]
+yaml = ["PyYAML (>=3.10)"]
+zookeeper = ["kazoo (>=2.8.0)"]
+
+[[package]]
+name = "lazy-loader"
+version = "0.4"
+description = "Makes it easy to load subpackages and functions on demand."
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "lazy_loader-0.4-py3-none-any.whl", hash = "sha256:342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc"},
+ {file = "lazy_loader-0.4.tar.gz", hash = "sha256:47c75182589b91a4e1a85a136c074285a5ad4d9f39c63e0d7fb76391c4574cd1"},
+]
+
+[package.dependencies]
+packaging = "*"
+
+[package.extras]
+dev = ["changelist (==0.5)"]
+lint = ["pre-commit (==3.7.0)"]
+test = ["pytest (>=7.4)", "pytest-cov (>=4.1)"]
+
+[[package]]
+name = "mako"
+version = "1.3.2"
+description = "A super-fast templating language that borrows the best ideas from the existing templating languages."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "Mako-1.3.2-py3-none-any.whl", hash = "sha256:32a99d70754dfce237019d17ffe4a282d2d3351b9c476e90d8a60e63f133b80c"},
+ {file = "Mako-1.3.2.tar.gz", hash = "sha256:2a0c8ad7f6274271b3bb7467dd37cf9cc6dab4bc19cb69a4ef10669402de698e"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=0.9.2"
+
+[package.extras]
+babel = ["Babel"]
+lingua = ["lingua"]
+testing = ["pytest"]
+
+[[package]]
+name = "markdown"
+version = "3.8"
+description = "Python implementation of John Gruber's Markdown."
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc"},
+ {file = "markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"},
+]
+
+[package.extras]
+docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
+testing = ["coverage", "pyyaml"]
+
+[[package]]
+name = "markupsafe"
+version = "2.0.1"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.6"
+groups = ["main", "docs"]
+files = [
+ {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
+ {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
+]
+
+[[package]]
+name = "matplotlib-inline"
+version = "0.1.7"
+description = "Inline Matplotlib backend for Jupyter"
+optional = false
+python-versions = ">=3.8"
+groups = ["main", "dev"]
+files = [
+ {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"},
+ {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"},
+]
+
+[package.dependencies]
+traitlets = "*"
+
+[[package]]
+name = "mccabe"
+version = "0.7.0"
+description = "McCabe checker, plugin for flake8"
+optional = false
+python-versions = ">=3.6"
+groups = ["dev"]
+files = [
+ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
+ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
+]
+
+[[package]]
+name = "mistune"
+version = "3.1.2"
+description = "A sane and fast Markdown parser with useful plugins and renderers"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "mistune-3.1.2-py3-none-any.whl", hash = "sha256:4b47731332315cdca99e0ded46fc0004001c1299ff773dfb48fbe1fd226de319"},
+ {file = "mistune-3.1.2.tar.gz", hash = "sha256:733bf018ba007e8b5f2d3a9eb624034f6ee26c4ea769a98ec533ee111d504dff"},
+]
+
+[[package]]
+name = "multidict"
+version = "6.7.0"
+description = "multidict implementation"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "multidict-6.7.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9f474ad5acda359c8758c8accc22032c6abe6dc87a8be2440d097785e27a9349"},
+ {file = "multidict-6.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a9db5a870f780220e931d0002bbfd88fb53aceb6293251e2c839415c1b20e"},
+ {file = "multidict-6.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03ca744319864e92721195fa28c7a3b2bc7b686246b35e4078c1e4d0eb5466d3"},
+ {file = "multidict-6.7.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f0e77e3c0008bc9316e662624535b88d360c3a5d3f81e15cf12c139a75250046"},
+ {file = "multidict-6.7.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08325c9e5367aa379a3496aa9a022fe8837ff22e00b94db256d3a1378c76ab32"},
+ {file = "multidict-6.7.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e2862408c99f84aa571ab462d25236ef9cb12a602ea959ba9c9009a54902fc73"},
+ {file = "multidict-6.7.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d72a9a2d885f5c208b0cb91ff2ed43636bb7e345ec839ff64708e04f69a13cc"},
+ {file = "multidict-6.7.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:478cc36476687bac1514d651cbbaa94b86b0732fb6855c60c673794c7dd2da62"},
+ {file = "multidict-6.7.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6843b28b0364dc605f21481c90fadb5f60d9123b442eb8a726bb74feef588a84"},
+ {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23bfeee5316266e5ee2d625df2d2c602b829435fc3a235c2ba2131495706e4a0"},
+ {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:680878b9f3d45c31e1f730eef731f9b0bc1da456155688c6745ee84eb818e90e"},
+ {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:eb866162ef2f45063acc7a53a88ef6fe8bf121d45c30ea3c9cd87ce7e191a8d4"},
+ {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:df0e3bf7993bdbeca5ac25aa859cf40d39019e015c9c91809ba7093967f7a648"},
+ {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:661709cdcd919a2ece2234f9bae7174e5220c80b034585d7d8a755632d3e2111"},
+ {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:096f52730c3fb8ed419db2d44391932b63891b2c5ed14850a7e215c0ba9ade36"},
+ {file = "multidict-6.7.0-cp310-cp310-win32.whl", hash = "sha256:afa8a2978ec65d2336305550535c9c4ff50ee527914328c8677b3973ade52b85"},
+ {file = "multidict-6.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:b15b3afff74f707b9275d5ba6a91ae8f6429c3ffb29bbfd216b0b375a56f13d7"},
+ {file = "multidict-6.7.0-cp310-cp310-win_arm64.whl", hash = "sha256:4b73189894398d59131a66ff157837b1fafea9974be486d036bb3d32331fdbf0"},
+ {file = "multidict-6.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc"},
+ {file = "multidict-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721"},
+ {file = "multidict-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6"},
+ {file = "multidict-6.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c"},
+ {file = "multidict-6.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7"},
+ {file = "multidict-6.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7"},
+ {file = "multidict-6.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9"},
+ {file = "multidict-6.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8"},
+ {file = "multidict-6.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd"},
+ {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb"},
+ {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6"},
+ {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2"},
+ {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff"},
+ {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b"},
+ {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34"},
+ {file = "multidict-6.7.0-cp311-cp311-win32.whl", hash = "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff"},
+ {file = "multidict-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81"},
+ {file = "multidict-6.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912"},
+ {file = "multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184"},
+ {file = "multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45"},
+ {file = "multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa"},
+ {file = "multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7"},
+ {file = "multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e"},
+ {file = "multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546"},
+ {file = "multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4"},
+ {file = "multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1"},
+ {file = "multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d"},
+ {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304"},
+ {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12"},
+ {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62"},
+ {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0"},
+ {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a"},
+ {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8"},
+ {file = "multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4"},
+ {file = "multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b"},
+ {file = "multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec"},
+ {file = "multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6"},
+ {file = "multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159"},
+ {file = "multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca"},
+ {file = "multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8"},
+ {file = "multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60"},
+ {file = "multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4"},
+ {file = "multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f"},
+ {file = "multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf"},
+ {file = "multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32"},
+ {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036"},
+ {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec"},
+ {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e"},
+ {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64"},
+ {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd"},
+ {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288"},
+ {file = "multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17"},
+ {file = "multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390"},
+ {file = "multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e"},
+ {file = "multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00"},
+ {file = "multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb"},
+ {file = "multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b"},
+ {file = "multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c"},
+ {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1"},
+ {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b"},
+ {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5"},
+ {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad"},
+ {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c"},
+ {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5"},
+ {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10"},
+ {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754"},
+ {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c"},
+ {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762"},
+ {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6"},
+ {file = "multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d"},
+ {file = "multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6"},
+ {file = "multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792"},
+ {file = "multidict-6.7.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842"},
+ {file = "multidict-6.7.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b"},
+ {file = "multidict-6.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38"},
+ {file = "multidict-6.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128"},
+ {file = "multidict-6.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34"},
+ {file = "multidict-6.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99"},
+ {file = "multidict-6.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202"},
+ {file = "multidict-6.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1"},
+ {file = "multidict-6.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3"},
+ {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d"},
+ {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6"},
+ {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7"},
+ {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb"},
+ {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f"},
+ {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f"},
+ {file = "multidict-6.7.0-cp314-cp314-win32.whl", hash = "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885"},
+ {file = "multidict-6.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c"},
+ {file = "multidict-6.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000"},
+ {file = "multidict-6.7.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63"},
+ {file = "multidict-6.7.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718"},
+ {file = "multidict-6.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2"},
+ {file = "multidict-6.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e"},
+ {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064"},
+ {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e"},
+ {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd"},
+ {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a"},
+ {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96"},
+ {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e"},
+ {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599"},
+ {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394"},
+ {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38"},
+ {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9"},
+ {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0"},
+ {file = "multidict-6.7.0-cp314-cp314t-win32.whl", hash = "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13"},
+ {file = "multidict-6.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd"},
+ {file = "multidict-6.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827"},
+ {file = "multidict-6.7.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:363eb68a0a59bd2303216d2346e6c441ba10d36d1f9969fcb6f1ba700de7bb5c"},
+ {file = "multidict-6.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d874eb056410ca05fed180b6642e680373688efafc7f077b2a2f61811e873a40"},
+ {file = "multidict-6.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b55d5497b51afdfde55925e04a022f1de14d4f4f25cdfd4f5d9b0aa96166851"},
+ {file = "multidict-6.7.0-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f8e5c0031b90ca9ce555e2e8fd5c3b02a25f14989cbc310701823832c99eb687"},
+ {file = "multidict-6.7.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cf41880c991716f3c7cec48e2f19ae4045fc9db5fc9cff27347ada24d710bb5"},
+ {file = "multidict-6.7.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cfc12a8630a29d601f48d47787bd7eb730e475e83edb5d6c5084317463373eb"},
+ {file = "multidict-6.7.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3996b50c3237c4aec17459217c1e7bbdead9a22a0fcd3c365564fbd16439dde6"},
+ {file = "multidict-6.7.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7f5170993a0dd3ab871c74f45c0a21a4e2c37a2f2b01b5f722a2ad9c6650469e"},
+ {file = "multidict-6.7.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ec81878ddf0e98817def1e77d4f50dae5ef5b0e4fe796fae3bd674304172416e"},
+ {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9281bf5b34f59afbc6b1e477a372e9526b66ca446f4bf62592839c195a718b32"},
+ {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:68af405971779d8b37198726f2b6fe3955db846fee42db7a4286fc542203934c"},
+ {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3ba3ef510467abb0667421a286dc906e30eb08569365f5cdb131d7aff7c2dd84"},
+ {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b61189b29081a20c7e4e0b49b44d5d44bb0dc92be3c6d06a11cc043f81bf9329"},
+ {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fb287618b9c7aa3bf8d825f02d9201b2f13078a5ed3b293c8f4d953917d84d5e"},
+ {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:521f33e377ff64b96c4c556b81c55d0cfffb96a11c194fd0c3f1e56f3d8dd5a4"},
+ {file = "multidict-6.7.0-cp39-cp39-win32.whl", hash = "sha256:ce8fdc2dca699f8dbf055a61d73eaa10482569ad20ee3c36ef9641f69afa8c91"},
+ {file = "multidict-6.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:7e73299c99939f089dd9b2120a04a516b95cdf8c1cd2b18c53ebf0de80b1f18f"},
+ {file = "multidict-6.7.0-cp39-cp39-win_arm64.whl", hash = "sha256:6bdce131e14b04fd34a809b6380dbfd826065c3e2fe8a50dbae659fa0c390546"},
+ {file = "multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3"},
+ {file = "multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5"},
+]
+
+[[package]]
+name = "mypy-extensions"
+version = "1.1.0"
+description = "Type system extensions for programs checked with the mypy type checker."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"},
+ {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"},
+]
+
+[[package]]
+name = "nbclient"
+version = "0.10.2"
+description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor."
+optional = false
+python-versions = ">=3.9.0"
+groups = ["main"]
+files = [
+ {file = "nbclient-0.10.2-py3-none-any.whl", hash = "sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d"},
+ {file = "nbclient-0.10.2.tar.gz", hash = "sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193"},
+]
+
+[package.dependencies]
+jupyter-client = ">=6.1.12"
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
+nbformat = ">=5.1"
+traitlets = ">=5.4"
+
+[package.extras]
+dev = ["pre-commit"]
+docs = ["autodoc-traits", "flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "mock", "moto", "myst-parser", "nbconvert (>=7.1.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling", "testpath", "xmltodict"]
+test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.1.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"]
+
+[[package]]
+name = "nbconvert"
+version = "7.16.6"
+description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "nbconvert-7.16.6-py3-none-any.whl", hash = "sha256:1375a7b67e0c2883678c48e506dc320febb57685e5ee67faa51b18a90f3a712b"},
+ {file = "nbconvert-7.16.6.tar.gz", hash = "sha256:576a7e37c6480da7b8465eefa66c17844243816ce1ccc372633c6b71c3c0f582"},
+]
+
+[package.dependencies]
+beautifulsoup4 = "*"
+bleach = {version = "!=5.0.0", extras = ["css"]}
+defusedxml = "*"
+jinja2 = ">=3.0"
+jupyter-core = ">=4.7"
+jupyterlab-pygments = "*"
+markupsafe = ">=2.0"
+mistune = ">=2.0.3,<4"
+nbclient = ">=0.5.0"
+nbformat = ">=5.7"
+packaging = "*"
+pandocfilters = ">=1.4.1"
+pygments = ">=2.4.1"
+traitlets = ">=5.1"
+
+[package.extras]
+all = ["flaky", "ipykernel", "ipython", "ipywidgets (>=7.5)", "myst-parser", "nbsphinx (>=0.2.12)", "playwright", "pydata-sphinx-theme", "pyqtwebengine (>=5.15)", "pytest (>=7)", "sphinx (==5.0.2)", "sphinxcontrib-spelling", "tornado (>=6.1)"]
+docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"]
+qtpdf = ["pyqtwebengine (>=5.15)"]
+qtpng = ["pyqtwebengine (>=5.15)"]
+serve = ["tornado (>=6.1)"]
+test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest (>=7)"]
+webpdf = ["playwright"]
+
+[[package]]
+name = "nbformat"
+version = "5.10.4"
+description = "The Jupyter Notebook format"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"},
+ {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"},
+]
+
+[package.dependencies]
+fastjsonschema = ">=2.15"
+jsonschema = ">=2.6"
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
+traitlets = ">=5.1"
+
+[package.extras]
+docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"]
+test = ["pep440", "pre-commit", "pytest", "testpath"]
+
+[[package]]
+name = "networkx"
+version = "3.5"
+description = "Python package for creating and manipulating graphs and networks"
+optional = false
+python-versions = ">=3.11"
+groups = ["main"]
+files = [
+ {file = "networkx-3.5-py3-none-any.whl", hash = "sha256:0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec"},
+ {file = "networkx-3.5.tar.gz", hash = "sha256:d4c6f9cf81f52d69230866796b82afbccdec3db7ae4fbd1b65ea750feed50037"},
+]
+
+[package.extras]
+default = ["matplotlib (>=3.8)", "numpy (>=1.25)", "pandas (>=2.0)", "scipy (>=1.11.2)"]
+developer = ["mypy (>=1.15)", "pre-commit (>=4.1)"]
+doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=10)", "pydata-sphinx-theme (>=0.16)", "sphinx (>=8.0)", "sphinx-gallery (>=0.18)", "texext (>=0.6.7)"]
+example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy (>=0.7.2)", "osmnx (>=2.0.0)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"]
+extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"]
+test = ["pytest (>=7.2)", "pytest-cov (>=4.0)", "pytest-xdist (>=3.0)"]
+test-extras = ["pytest-mpl", "pytest-randomly"]
+
+[[package]]
+name = "newrelic"
+version = "10.8.1"
+description = "New Relic Python Agent"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "newrelic-10.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c1c8438138ca530ecbb4a8d52805520b6815e65e93856739494aa657e1b464a"},
+ {file = "newrelic-10.8.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:824d36a9be37c43f7d66bed46689c1c2168eba60c591299e932684e03eb10e42"},
+ {file = "newrelic-10.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e2d02e6edd5a9c0e2229e6ca1fa114d9ee95e7c137d3eaa9de3ce8b1ce73b62b"},
+ {file = "newrelic-10.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0c5f96c2ec732258980ea1c2ae8e66ec834ff4c40a815ffdacf3154f1e53d3d5"},
+ {file = "newrelic-10.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03552deef7ee3d9d40b579beca702ac65105d7b5ebd603da0520961b96acadfe"},
+ {file = "newrelic-10.8.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:600aa9b4dafcc4e0d16cc9c0bd40e2fe07a5fa3aa03f4293ba69045738885473"},
+ {file = "newrelic-10.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:75dbdceb1601368becaf0e37af98eadcd5c41d0fb362b906d11eb6697528b52b"},
+ {file = "newrelic-10.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a928b17f4c4d729f0522b3029da5ece1d32d2c5f0a89d500a037619bc53a0b06"},
+ {file = "newrelic-10.8.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:055a8316e3eb1ddb230495928c5d4ad71ad18d11a295092123a1de9f01efa385"},
+ {file = "newrelic-10.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a25ce0228eb104274b71eadf110971c51c90f80c7c6f31f62b3fda4d732eb0a3"},
+ {file = "newrelic-10.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c025d52c45b17abaaeb1907e18104567e65c0d36f855a8fe9834cf105e0ca46"},
+ {file = "newrelic-10.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:28c26c54b6be6a4827ce0cbd056bbb12c5aec148a7de0b664438cc35bb93afdb"},
+ {file = "newrelic-10.8.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1688c9dcfb101b30acb4baf2e2f45159c3d298cdd585204eedf4642e2850fe3"},
+ {file = "newrelic-10.8.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b68067a89eca771e766370fdf3a7f4dd5e02372957051e54fad23096b93e1819"},
+ {file = "newrelic-10.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59055c2265183f7ec9fff9c657451accba6f84eb0ceb5dca9a6dcaa012f2df6b"},
+ {file = "newrelic-10.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b3c70ef477e91e9c4419905940769c8223a9d21bf388473687aa500998f23543"},
+ {file = "newrelic-10.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1ce54252d6e3c0b02887b284b58011c9b5a0d82deafc2dc9313be9cb757a720"},
+ {file = "newrelic-10.8.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9a053f1ba62b89c2a1543a8a55e36bc1cd3c77a39a98744927ba298ce4e3af3"},
+ {file = "newrelic-10.8.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5444474ba9aa6a08e0235b931c4506c9d78911d9bdbb3a68132107186bd53b35"},
+ {file = "newrelic-10.8.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89d75646853ce429ba7fe6d7a0d50100107040525094d8f14b965660a6ea41f7"},
+ {file = "newrelic-10.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9a3410ea09e70af92181db485b7772ae7c9243d4605dba20e9dd6cea08e0a1"},
+ {file = "newrelic-10.8.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7396a8e0b52ce7cb8a6f5cbef5196da7356b3197421617648b9c6d861aa9fe3"},
+ {file = "newrelic-10.8.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:457c74a3fbc4484111f0e5473dc8186da5cd371ced820fb28107fed9790ddc55"},
+ {file = "newrelic-10.8.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:935fdb99883636da4f8aca3d44646c0262c74e1322342e86f0ab0016ecd4cb37"},
+ {file = "newrelic-10.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b823bd4ef787e47f4a3c39a03ba9634dfadee609bb11d050634316f376a9368b"},
+ {file = "newrelic-10.8.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17a696256c76af9f186af93aa4ef97e9b3e2bd832bec263f5e0b69f47e7ad2f6"},
+ {file = "newrelic-10.8.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c63924d7748555af011de1d04c0f51069d78fb45112ded407cec39d171763cd3"},
+ {file = "newrelic-10.8.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d0b01b8a7ff3596825d99ef88b5c04ad6a312d0c3969e97651fda3a35b6212c2"},
+ {file = "newrelic-10.8.1.tar.gz", hash = "sha256:4eac63a95a4565198c36a4ffacb3798bd53affb6fb188531e201f8eb239ee86b"},
+]
+
+[package.extras]
+infinite-tracing = ["grpcio", "protobuf"]
+
+[[package]]
+name = "numpy"
+version = "2.3.3"
+description = "Fundamental package for array computing in Python"
+optional = false
+python-versions = ">=3.11"
+groups = ["main"]
+files = [
+ {file = "numpy-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ffc4f5caba7dfcbe944ed674b7eef683c7e94874046454bb79ed7ee0236f59d"},
+ {file = "numpy-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7e946c7170858a0295f79a60214424caac2ffdb0063d4d79cb681f9aa0aa569"},
+ {file = "numpy-2.3.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:cd4260f64bc794c3390a63bf0728220dd1a68170c169088a1e0dfa2fde1be12f"},
+ {file = "numpy-2.3.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:f0ddb4b96a87b6728df9362135e764eac3cfa674499943ebc44ce96c478ab125"},
+ {file = "numpy-2.3.3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:afd07d377f478344ec6ca2b8d4ca08ae8bd44706763d1efb56397de606393f48"},
+ {file = "numpy-2.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bc92a5dedcc53857249ca51ef29f5e5f2f8c513e22cfb90faeb20343b8c6f7a6"},
+ {file = "numpy-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7af05ed4dc19f308e1d9fc759f36f21921eb7bbfc82843eeec6b2a2863a0aefa"},
+ {file = "numpy-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:433bf137e338677cebdd5beac0199ac84712ad9d630b74eceeb759eaa45ddf30"},
+ {file = "numpy-2.3.3-cp311-cp311-win32.whl", hash = "sha256:eb63d443d7b4ffd1e873f8155260d7f58e7e4b095961b01c91062935c2491e57"},
+ {file = "numpy-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:ec9d249840f6a565f58d8f913bccac2444235025bbb13e9a4681783572ee3caa"},
+ {file = "numpy-2.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:74c2a948d02f88c11a3c075d9733f1ae67d97c6bdb97f2bb542f980458b257e7"},
+ {file = "numpy-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cfdd09f9c84a1a934cde1eec2267f0a43a7cd44b2cca4ff95b7c0d14d144b0bf"},
+ {file = "numpy-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb32e3cf0f762aee47ad1ddc6672988f7f27045b0783c887190545baba73aa25"},
+ {file = "numpy-2.3.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:396b254daeb0a57b1fe0ecb5e3cff6fa79a380fa97c8f7781a6d08cd429418fe"},
+ {file = "numpy-2.3.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:067e3d7159a5d8f8a0b46ee11148fc35ca9b21f61e3c49fbd0a027450e65a33b"},
+ {file = "numpy-2.3.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c02d0629d25d426585fb2e45a66154081b9fa677bc92a881ff1d216bc9919a8"},
+ {file = "numpy-2.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9192da52b9745f7f0766531dcfa978b7763916f158bb63bdb8a1eca0068ab20"},
+ {file = "numpy-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cd7de500a5b66319db419dc3c345244404a164beae0d0937283b907d8152e6ea"},
+ {file = "numpy-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93d4962d8f82af58f0b2eb85daaf1b3ca23fe0a85d0be8f1f2b7bb46034e56d7"},
+ {file = "numpy-2.3.3-cp312-cp312-win32.whl", hash = "sha256:5534ed6b92f9b7dca6c0a19d6df12d41c68b991cef051d108f6dbff3babc4ebf"},
+ {file = "numpy-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:497d7cad08e7092dba36e3d296fe4c97708c93daf26643a1ae4b03f6294d30eb"},
+ {file = "numpy-2.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:ca0309a18d4dfea6fc6262a66d06c26cfe4640c3926ceec90e57791a82b6eee5"},
+ {file = "numpy-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f5415fb78995644253370985342cd03572ef8620b934da27d77377a2285955bf"},
+ {file = "numpy-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d00de139a3324e26ed5b95870ce63be7ec7352171bc69a4cf1f157a48e3eb6b7"},
+ {file = "numpy-2.3.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9dc13c6a5829610cc07422bc74d3ac083bd8323f14e2827d992f9e52e22cd6a6"},
+ {file = "numpy-2.3.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d79715d95f1894771eb4e60fb23f065663b2298f7d22945d66877aadf33d00c7"},
+ {file = "numpy-2.3.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952cfd0748514ea7c3afc729a0fc639e61655ce4c55ab9acfab14bda4f402b4c"},
+ {file = "numpy-2.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b83648633d46f77039c29078751f80da65aa64d5622a3cd62aaef9d835b6c93"},
+ {file = "numpy-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b001bae8cea1c7dfdb2ae2b017ed0a6f2102d7a70059df1e338e307a4c78a8ae"},
+ {file = "numpy-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8e9aced64054739037d42fb84c54dd38b81ee238816c948c8f3ed134665dcd86"},
+ {file = "numpy-2.3.3-cp313-cp313-win32.whl", hash = "sha256:9591e1221db3f37751e6442850429b3aabf7026d3b05542d102944ca7f00c8a8"},
+ {file = "numpy-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f0dadeb302887f07431910f67a14d57209ed91130be0adea2f9793f1a4f817cf"},
+ {file = "numpy-2.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:3c7cf302ac6e0b76a64c4aecf1a09e51abd9b01fc7feee80f6c43e3ab1b1dbc5"},
+ {file = "numpy-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:eda59e44957d272846bb407aad19f89dc6f58fecf3504bd144f4c5cf81a7eacc"},
+ {file = "numpy-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:823d04112bc85ef5c4fda73ba24e6096c8f869931405a80aa8b0e604510a26bc"},
+ {file = "numpy-2.3.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:40051003e03db4041aa325da2a0971ba41cf65714e65d296397cc0e32de6018b"},
+ {file = "numpy-2.3.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ee9086235dd6ab7ae75aba5662f582a81ced49f0f1c6de4260a78d8f2d91a19"},
+ {file = "numpy-2.3.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94fcaa68757c3e2e668ddadeaa86ab05499a70725811e582b6a9858dd472fb30"},
+ {file = "numpy-2.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da1a74b90e7483d6ce5244053399a614b1d6b7bc30a60d2f570e5071f8959d3e"},
+ {file = "numpy-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2990adf06d1ecee3b3dcbb4977dfab6e9f09807598d647f04d385d29e7a3c3d3"},
+ {file = "numpy-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ed635ff692483b8e3f0fcaa8e7eb8a75ee71aa6d975388224f70821421800cea"},
+ {file = "numpy-2.3.3-cp313-cp313t-win32.whl", hash = "sha256:a333b4ed33d8dc2b373cc955ca57babc00cd6f9009991d9edc5ddbc1bac36bcd"},
+ {file = "numpy-2.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4384a169c4d8f97195980815d6fcad04933a7e1ab3b530921c3fef7a1c63426d"},
+ {file = "numpy-2.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:75370986cc0bc66f4ce5110ad35aae6d182cc4ce6433c40ad151f53690130bf1"},
+ {file = "numpy-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cd052f1fa6a78dee696b58a914b7229ecfa41f0a6d96dc663c1220a55e137593"},
+ {file = "numpy-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:414a97499480067d305fcac9716c29cf4d0d76db6ebf0bf3cbce666677f12652"},
+ {file = "numpy-2.3.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:50a5fe69f135f88a2be9b6ca0481a68a136f6febe1916e4920e12f1a34e708a7"},
+ {file = "numpy-2.3.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:b912f2ed2b67a129e6a601e9d93d4fa37bef67e54cac442a2f588a54afe5c67a"},
+ {file = "numpy-2.3.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e318ee0596d76d4cb3d78535dc005fa60e5ea348cd131a51e99d0bdbe0b54fe"},
+ {file = "numpy-2.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce020080e4a52426202bdb6f7691c65bb55e49f261f31a8f506c9f6bc7450421"},
+ {file = "numpy-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e6687dc183aa55dae4a705b35f9c0f8cb178bcaa2f029b241ac5356221d5c021"},
+ {file = "numpy-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d8f3b1080782469fdc1718c4ed1d22549b5fb12af0d57d35e992158a772a37cf"},
+ {file = "numpy-2.3.3-cp314-cp314-win32.whl", hash = "sha256:cb248499b0bc3be66ebd6578b83e5acacf1d6cb2a77f2248ce0e40fbec5a76d0"},
+ {file = "numpy-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:691808c2b26b0f002a032c73255d0bd89751425f379f7bcd22d140db593a96e8"},
+ {file = "numpy-2.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:9ad12e976ca7b10f1774b03615a2a4bab8addce37ecc77394d8e986927dc0dfe"},
+ {file = "numpy-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9cc48e09feb11e1db00b320e9d30a4151f7369afb96bd0e48d942d09da3a0d00"},
+ {file = "numpy-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:901bf6123879b7f251d3631967fd574690734236075082078e0571977c6a8e6a"},
+ {file = "numpy-2.3.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f025652034199c301049296b59fa7d52c7e625017cae4c75d8662e377bf487d"},
+ {file = "numpy-2.3.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:533ca5f6d325c80b6007d4d7fb1984c303553534191024ec6a524a4c92a5935a"},
+ {file = "numpy-2.3.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0edd58682a399824633b66885d699d7de982800053acf20be1eaa46d92009c54"},
+ {file = "numpy-2.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:367ad5d8fbec5d9296d18478804a530f1191e24ab4d75ab408346ae88045d25e"},
+ {file = "numpy-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8f6ac61a217437946a1fa48d24c47c91a0c4f725237871117dea264982128097"},
+ {file = "numpy-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:179a42101b845a816d464b6fe9a845dfaf308fdfc7925387195570789bb2c970"},
+ {file = "numpy-2.3.3-cp314-cp314t-win32.whl", hash = "sha256:1250c5d3d2562ec4174bce2e3a1523041595f9b651065e4a4473f5f48a6bc8a5"},
+ {file = "numpy-2.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b37a0b2e5935409daebe82c1e42274d30d9dd355852529eab91dab8dcca7419f"},
+ {file = "numpy-2.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b"},
+ {file = "numpy-2.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1e02c7159791cd481e1e6d5ddd766b62a4d5acf8df4d4d1afe35ee9c5c33a41e"},
+ {file = "numpy-2.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:dca2d0fc80b3893ae72197b39f69d55a3cd8b17ea1b50aa4c62de82419936150"},
+ {file = "numpy-2.3.3-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:99683cbe0658f8271b333a1b1b4bb3173750ad59c0c61f5bbdc5b318918fffe3"},
+ {file = "numpy-2.3.3-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:d9d537a39cc9de668e5cd0e25affb17aec17b577c6b3ae8a3d866b479fbe88d0"},
+ {file = "numpy-2.3.3-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8596ba2f8af5f93b01d97563832686d20206d303024777f6dfc2e7c7c3f1850e"},
+ {file = "numpy-2.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1ec5615b05369925bd1125f27df33f3b6c8bc10d788d5999ecd8769a1fa04db"},
+ {file = "numpy-2.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2e267c7da5bf7309670523896df97f93f6e469fb931161f483cd6882b3b1a5dc"},
+ {file = "numpy-2.3.3.tar.gz", hash = "sha256:ddc7c39727ba62b80dfdbedf400d1c10ddfa8eefbd7ec8dcb118be8b56d31029"},
+]
+
+[[package]]
+name = "oauthlib"
+version = "3.2.2"
+description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
+optional = false
+python-versions = ">=3.6"
+groups = ["main"]
+files = [
+ {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"},
+ {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"},
+]
+
+[package.extras]
+rsa = ["cryptography (>=3.0.0)"]
+signals = ["blinker (>=1.4.0)"]
+signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"]
+
+[[package]]
+name = "olefile"
+version = "0.47"
+description = "Python package to parse, read and write Microsoft OLE2 files (Structured Storage or Compound Document, Microsoft Office)"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+groups = ["main"]
+files = [
+ {file = "olefile-0.47-py2.py3-none-any.whl", hash = "sha256:543c7da2a7adadf21214938bb79c83ea12b473a4b6ee4ad4bf854e7715e13d1f"},
+ {file = "olefile-0.47.zip", hash = "sha256:599383381a0bf3dfbd932ca0ca6515acd174ed48870cbf7fee123d698c192c1c"},
+]
+
+[package.extras]
+tests = ["pytest", "pytest-cov"]
+
+[[package]]
+name = "openpyxl"
+version = "3.1.5"
+description = "A Python library to read/write Excel 2010 xlsx/xlsm files"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"},
+ {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"},
+]
+
+[package.dependencies]
+et-xmlfile = "*"
+
+[[package]]
+name = "orderedmultidict"
+version = "1.0.1"
+description = "Ordered Multivalue Dictionary"
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "orderedmultidict-1.0.1-py2.py3-none-any.whl", hash = "sha256:43c839a17ee3cdd62234c47deca1a8508a3f2ca1d0678a3bf791c87cf84adbf3"},
+ {file = "orderedmultidict-1.0.1.tar.gz", hash = "sha256:04070bbb5e87291cc9bfa51df413677faf2141c73c61d2a5f7b26bea3cd882ad"},
+]
+
+[package.dependencies]
+six = ">=1.8.0"
+
+[[package]]
+name = "packaging"
+version = "25.0"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.8"
+groups = ["main", "dev", "docs"]
+files = [
+ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"},
+ {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"},
+]
+
+[[package]]
+name = "pandas"
+version = "2.2.3"
+description = "Powerful data structures for data analysis, time series, and statistics"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"},
+ {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"},
+ {file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"},
+ {file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"},
+ {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"},
+ {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"},
+ {file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"},
+ {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"},
+ {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"},
+ {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"},
+ {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"},
+ {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"},
+ {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"},
+ {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"},
+ {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"},
+ {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"},
+ {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"},
+ {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"},
+ {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"},
+ {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"},
+ {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"},
+ {file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"},
+ {file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"},
+ {file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"},
+ {file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"},
+ {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"},
+ {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"},
+ {file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"},
+ {file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"},
+ {file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"},
+ {file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"},
+ {file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"},
+ {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"},
+ {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"},
+ {file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"},
+ {file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"},
+ {file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"},
+ {file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"},
+ {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"},
+ {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"},
+ {file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"},
+ {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"},
+]
+
+[package.dependencies]
+numpy = {version = ">=1.26.0", markers = "python_version >= \"3.12\""}
+python-dateutil = ">=2.8.2"
+pytz = ">=2020.1"
+tzdata = ">=2022.7"
+
+[package.extras]
+all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"]
+aws = ["s3fs (>=2022.11.0)"]
+clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"]
+compression = ["zstandard (>=0.19.0)"]
+computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"]
+consortium-standard = ["dataframe-api-compat (>=0.1.7)"]
+excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"]
+feather = ["pyarrow (>=10.0.1)"]
+fss = ["fsspec (>=2022.11.0)"]
+gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"]
+hdf5 = ["tables (>=3.8.0)"]
+html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"]
+mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"]
+output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"]
+parquet = ["pyarrow (>=10.0.1)"]
+performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"]
+plot = ["matplotlib (>=3.6.3)"]
+postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"]
+pyarrow = ["pyarrow (>=10.0.1)"]
+spss = ["pyreadstat (>=1.2.0)"]
+sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"]
+test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
+xml = ["lxml (>=4.9.2)"]
+
+[[package]]
+name = "pandocfilters"
+version = "1.5.1"
+description = "Utilities for writing pandoc filters in python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+groups = ["main"]
+files = [
+ {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"},
+ {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"},
+]
+
+[[package]]
+name = "parso"
+version = "0.8.5"
+description = "A Python Parser"
+optional = false
+python-versions = ">=3.6"
+groups = ["main", "dev"]
+files = [
+ {file = "parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887"},
+ {file = "parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a"},
+]
+
+[package.extras]
+qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
+testing = ["docopt", "pytest"]
+
+[[package]]
+name = "pathspec"
+version = "0.12.1"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
+ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
+]
+
+[[package]]
+name = "pbr"
+version = "7.0.1"
+description = "Python Build Reasonableness"
+optional = false
+python-versions = ">=2.6"
+groups = ["main"]
+files = [
+ {file = "pbr-7.0.1-py2.py3-none-any.whl", hash = "sha256:32df5156fbeccb6f8a858d1ebc4e465dcf47d6cc7a4895d5df9aa951c712fc35"},
+ {file = "pbr-7.0.1.tar.gz", hash = "sha256:3ecbcb11d2b8551588ec816b3756b1eb4394186c3b689b17e04850dfc20f7e57"},
+]
+
+[package.dependencies]
+setuptools = "*"
+
+[[package]]
+name = "pexpect"
+version = "4.9.0"
+description = "Pexpect allows easy control of interactive console applications."
+optional = false
+python-versions = "*"
+groups = ["main", "dev"]
+markers = "sys_platform != \"win32\""
+files = [
+ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"},
+ {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"},
+]
+
+[package.dependencies]
+ptyprocess = ">=0.5"
+
+[[package]]
+name = "pickleshare"
+version = "0.7.5"
+description = "Tiny 'shelve'-like database with concurrency support"
+optional = false
+python-versions = "*"
+groups = ["main", "dev"]
+files = [
+ {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
+ {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
+]
+
+[[package]]
+name = "pillow"
+version = "11.2.1"
+description = "Python Imaging Library (Fork)"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "pillow-11.2.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:d57a75d53922fc20c165016a20d9c44f73305e67c351bbc60d1adaf662e74047"},
+ {file = "pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:127bf6ac4a5b58b3d32fc8289656f77f80567d65660bc46f72c0d77e6600cc95"},
+ {file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ba4be812c7a40280629e55ae0b14a0aafa150dd6451297562e1764808bbe61"},
+ {file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8bd62331e5032bc396a93609982a9ab6b411c05078a52f5fe3cc59234a3abd1"},
+ {file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:562d11134c97a62fe3af29581f083033179f7ff435f78392565a1ad2d1c2c45c"},
+ {file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c97209e85b5be259994eb5b69ff50c5d20cca0f458ef9abd835e262d9d88b39d"},
+ {file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0c3e6d0f59171dfa2e25d7116217543310908dfa2770aa64b8f87605f8cacc97"},
+ {file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc1c3bc53befb6096b84165956e886b1729634a799e9d6329a0c512ab651e579"},
+ {file = "pillow-11.2.1-cp310-cp310-win32.whl", hash = "sha256:312c77b7f07ab2139924d2639860e084ec2a13e72af54d4f08ac843a5fc9c79d"},
+ {file = "pillow-11.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:9bc7ae48b8057a611e5fe9f853baa88093b9a76303937449397899385da06fad"},
+ {file = "pillow-11.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:2728567e249cdd939f6cc3d1f049595c66e4187f3c34078cbc0a7d21c47482d2"},
+ {file = "pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70"},
+ {file = "pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf"},
+ {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7"},
+ {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8"},
+ {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600"},
+ {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788"},
+ {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e"},
+ {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e"},
+ {file = "pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6"},
+ {file = "pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193"},
+ {file = "pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7"},
+ {file = "pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f"},
+ {file = "pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b"},
+ {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d"},
+ {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4"},
+ {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d"},
+ {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4"},
+ {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443"},
+ {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c"},
+ {file = "pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3"},
+ {file = "pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941"},
+ {file = "pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb"},
+ {file = "pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28"},
+ {file = "pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830"},
+ {file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0"},
+ {file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1"},
+ {file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f"},
+ {file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155"},
+ {file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14"},
+ {file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b"},
+ {file = "pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2"},
+ {file = "pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691"},
+ {file = "pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c"},
+ {file = "pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22"},
+ {file = "pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7"},
+ {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16"},
+ {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b"},
+ {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406"},
+ {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91"},
+ {file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751"},
+ {file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9"},
+ {file = "pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd"},
+ {file = "pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e"},
+ {file = "pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681"},
+ {file = "pillow-11.2.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:7491cf8a79b8eb867d419648fff2f83cb0b3891c8b36da92cc7f1931d46108c8"},
+ {file = "pillow-11.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b02d8f9cb83c52578a0b4beadba92e37d83a4ef11570a8688bbf43f4ca50909"},
+ {file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014ca0050c85003620526b0ac1ac53f56fc93af128f7546623cc8e31875ab928"},
+ {file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3692b68c87096ac6308296d96354eddd25f98740c9d2ab54e1549d6c8aea9d79"},
+ {file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:f781dcb0bc9929adc77bad571b8621ecb1e4cdef86e940fe2e5b5ee24fd33b35"},
+ {file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2b490402c96f907a166615e9a5afacf2519e28295f157ec3a2bb9bd57de638cb"},
+ {file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd6b20b93b3ccc9c1b597999209e4bc5cf2853f9ee66e3fc9a400a78733ffc9a"},
+ {file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4b835d89c08a6c2ee7781b8dd0a30209a8012b5f09c0a665b65b0eb3560b6f36"},
+ {file = "pillow-11.2.1-cp39-cp39-win32.whl", hash = "sha256:b10428b3416d4f9c61f94b494681280be7686bda15898a3a9e08eb66a6d92d67"},
+ {file = "pillow-11.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:6ebce70c3f486acf7591a3d73431fa504a4e18a9b97ff27f5f47b7368e4b9dd1"},
+ {file = "pillow-11.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:c27476257b2fdcd7872d54cfd119b3a9ce4610fb85c8e32b70b42e3680a29a1e"},
+ {file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9b7b0d4fd2635f54ad82785d56bc0d94f147096493a79985d0ab57aedd563156"},
+ {file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:aa442755e31c64037aa7c1cb186e0b369f8416c567381852c63444dd666fb772"},
+ {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d3348c95b766f54b76116d53d4cb171b52992a1027e7ca50c81b43b9d9e363"},
+ {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85d27ea4c889342f7e35f6d56e7e1cb345632ad592e8c51b693d7b7556043ce0"},
+ {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bf2c33d6791c598142f00c9c4c7d47f6476731c31081331664eb26d6ab583e01"},
+ {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e616e7154c37669fc1dfc14584f11e284e05d1c650e1c0f972f281c4ccc53193"},
+ {file = "pillow-11.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:39ad2e0f424394e3aebc40168845fee52df1394a4673a6ee512d840d14ab3013"},
+ {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed"},
+ {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c"},
+ {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd"},
+ {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076"},
+ {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b"},
+ {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f"},
+ {file = "pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044"},
+ {file = "pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6"},
+]
+
+[package.extras]
+docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"]
+fpx = ["olefile"]
+mic = ["olefile"]
+test-arrow = ["pyarrow"]
+tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "trove-classifiers (>=2024.10.12)"]
+typing = ["typing-extensions ; python_version < \"3.10\""]
+xmp = ["defusedxml"]
+
+[[package]]
+name = "platformdirs"
+version = "4.4.0"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"},
+ {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"},
+]
+
+[package.extras]
+docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"]
+type = ["mypy (>=1.14.1)"]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.9"
+groups = ["dev"]
+files = [
+ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"},
+ {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["coverage", "pytest", "pytest-benchmark"]
+
+[[package]]
+name = "prompt-toolkit"
+version = "3.0.52"
+description = "Library for building powerful interactive command lines in Python"
+optional = false
+python-versions = ">=3.8"
+groups = ["main", "dev"]
+files = [
+ {file = "prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955"},
+ {file = "prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855"},
+]
+
+[package.dependencies]
+wcwidth = "*"
+
+[[package]]
+name = "propcache"
+version = "0.4.0"
+description = "Accelerated property cache"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "propcache-0.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:779aaae64089e2f4992e993faea801925395d26bb5de4a47df7ef7f942c14f80"},
+ {file = "propcache-0.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:566552ed9b003030745e5bc7b402b83cf3cecae1bade95262d78543741786db5"},
+ {file = "propcache-0.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:944de70384c62d16d4a00c686b422aa75efbc67c4addaebefbb56475d1c16034"},
+ {file = "propcache-0.4.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e878553543ece1f8006d0ba4d096b40290580db173bfb18e16158045b9371335"},
+ {file = "propcache-0.4.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8659f995b19185179474b18de8755689e1f71e1334d05c14e1895caa4e409cf7"},
+ {file = "propcache-0.4.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7aa8cc5c94e682dce91cb4d12d7b81c01641f4ef5b3b3dc53325d43f0e3b9f2e"},
+ {file = "propcache-0.4.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da584d917a1a17f690fc726617fd2c3f3006ea959dae5bb07a5630f7b16f9f5f"},
+ {file = "propcache-0.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:892a072e5b19c3f324a4f8543c9f7e8fc2b0aa08579e46f69bdf0cfc1b440454"},
+ {file = "propcache-0.4.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c20d796210720455086ef3f85adc413d1e41d374742f9b439354f122bbc3b528"},
+ {file = "propcache-0.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:df7107a91126a495880576610ae989f19106e1900dd5218d08498391fa43b31d"},
+ {file = "propcache-0.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0b04ac2120c161416c866d0b6a4259e47e92231ff166b518cc0efb95777367c3"},
+ {file = "propcache-0.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1e7fa29c71ffa8d6a37324258737d09475f84715a6e8c350f67f0bc8e5e44993"},
+ {file = "propcache-0.4.0-cp310-cp310-win32.whl", hash = "sha256:01c0ebc172ca28e9d62876832befbf7f36080eee6ed9c9e00243de2a8089ad57"},
+ {file = "propcache-0.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:84f847e64f4d1a232e50460eebc1196642ee9b4c983612f41cd2d44fd2fe7c71"},
+ {file = "propcache-0.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:2166466a666a5bebc332cd209cad77d996fad925ca7e8a2a6310ba9e851ae641"},
+ {file = "propcache-0.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6a6a36b94c09711d6397d79006ca47901539fbc602c853d794c39abd6a326549"},
+ {file = "propcache-0.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:da47070e1340a1639aca6b1c18fe1f1f3d8d64d3a1f9ddc67b94475f44cd40f3"},
+ {file = "propcache-0.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:de536cf796abc5b58d11c0ad56580215d231d9554ea4bb6b8b1b3bed80aa3234"},
+ {file = "propcache-0.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f5c82af8e329c3cdc3e717dd3c7b2ff1a218b6de611f6ce76ee34967570a9de9"},
+ {file = "propcache-0.4.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:abe04e7aa5ab2e4056fcf3255ebee2071e4a427681f76d4729519e292c46ecc1"},
+ {file = "propcache-0.4.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:075ca32384294434344760fdcb95f7833e1d7cf7c4e55f0e726358140179da35"},
+ {file = "propcache-0.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:626ec13592928b677f48ff5861040b604b635e93d8e2162fb638397ea83d07e8"},
+ {file = "propcache-0.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:02e071548b6a376e173b0102c3f55dc16e7d055b5307d487e844c320e38cacf2"},
+ {file = "propcache-0.4.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:2af6de831a26f42a3f94592964becd8d7f238551786d7525807f02e53defbd13"},
+ {file = "propcache-0.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd6c6dba1a3b8949e08c4280071c86e38cb602f02e0ed6659234108c7a7cd710"},
+ {file = "propcache-0.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:783e91595cf9b66c2deda17f2e8748ae8591aa9f7c65dcab038872bfe83c5bb1"},
+ {file = "propcache-0.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c3f4b125285d354a627eb37f3ea7c13b8842c7c0d47783581d0df0e272dbf5f0"},
+ {file = "propcache-0.4.0-cp311-cp311-win32.whl", hash = "sha256:71c45f02ffbb8a21040ae816ceff7f6cd749ffac29fc0f9daa42dc1a9652d577"},
+ {file = "propcache-0.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:7d51f70f77950f8efafed4383865d3533eeee52d8a0dd1c35b65f24de41de4e0"},
+ {file = "propcache-0.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:858eaabd2191dd0da5272993ad08a748b5d3ae1aefabea8aee619b45c2af4a64"},
+ {file = "propcache-0.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:381c84a445efb8c9168f1393a5a7c566de22edc42bfe207a142fff919b37f5d9"},
+ {file = "propcache-0.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5a531d29d7b873b12730972237c48b1a4e5980b98cf21b3f09fa4710abd3a8c3"},
+ {file = "propcache-0.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cd6e22255ed73efeaaeb1765505a66a48a9ec9ebc919fce5ad490fe5e33b1555"},
+ {file = "propcache-0.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9a8d277dc218ddf04ec243a53ac309b1afcebe297c0526a8f82320139b56289"},
+ {file = "propcache-0.4.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:399c73201d88c856a994916200d7cba41d7687096f8eb5139eb68f02785dc3f7"},
+ {file = "propcache-0.4.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a1d5e474d43c238035b74ecf997f655afa67f979bae591ac838bb3fbe3076392"},
+ {file = "propcache-0.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22f589652ee38de96aa58dd219335604e09666092bc250c1d9c26a55bcef9932"},
+ {file = "propcache-0.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e5227da556b2939da6125cda1d5eecf9e412e58bc97b41e2f192605c3ccbb7c2"},
+ {file = "propcache-0.4.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:92bc43a1ab852310721ce856f40a3a352254aa6f5e26f0fad870b31be45bba2e"},
+ {file = "propcache-0.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:83ae2f5343f6f06f4c91ae530d95f56b415f768f9c401a5ee2a10459cf74370b"},
+ {file = "propcache-0.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:077a32977399dc05299b16e793210341a0b511eb0a86d1796873e83ce47334cc"},
+ {file = "propcache-0.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:94a278c45e6463031b5a8278e40a07edf2bcc3b5379510e22b6c1a6e6498c194"},
+ {file = "propcache-0.4.0-cp312-cp312-win32.whl", hash = "sha256:4c491462e1dc80f9deb93f428aad8d83bb286de212837f58eb48e75606e7726c"},
+ {file = "propcache-0.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cdb0cecafb528ab15ed89cdfed183074d15912d046d3e304955513b50a34b907"},
+ {file = "propcache-0.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:b2f29697d1110e8cdf7a39cc630498df0082d7898b79b731c1c863f77c6e8cfc"},
+ {file = "propcache-0.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e2d01fd53e89cb3d71d20b8c225a8c70d84660f2d223afc7ed7851a4086afe6d"},
+ {file = "propcache-0.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7dfa60953169d2531dd8ae306e9c27c5d4e5efe7a2ba77049e8afdaece062937"},
+ {file = "propcache-0.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:227892597953611fce2601d49f1d1f39786a6aebc2f253c2de775407f725a3f6"},
+ {file = "propcache-0.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e0a5bc019014531308fb67d86066d235daa7551baf2e00e1ea7b00531f6ea85"},
+ {file = "propcache-0.4.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6ebc6e2e65c31356310ddb6519420eaa6bb8c30fbd809d0919129c89dcd70f4c"},
+ {file = "propcache-0.4.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1927b78dd75fc31a7fdc76cc7039e39f3170cb1d0d9a271e60f0566ecb25211a"},
+ {file = "propcache-0.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b113feeda47f908562d9a6d0e05798ad2f83d4473c0777dafa2bc7756473218"},
+ {file = "propcache-0.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4596c12aa7e3bb2abf158ea8f79eb0fb4851606695d04ab846b2bb386f5690a1"},
+ {file = "propcache-0.4.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6d1f67dad8cc36e8abc2207a77f3f952ac80be7404177830a7af4635a34cbc16"},
+ {file = "propcache-0.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e6229ad15366cd8b6d6b4185c55dd48debf9ca546f91416ba2e5921ad6e210a6"},
+ {file = "propcache-0.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2a4bf309d057327f1f227a22ac6baf34a66f9af75e08c613e47c4d775b06d6c7"},
+ {file = "propcache-0.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c2e274f3d1cbb2ddcc7a55ce3739af0f8510edc68a7f37981b2258fa1eedc833"},
+ {file = "propcache-0.4.0-cp313-cp313-win32.whl", hash = "sha256:f114a3e1f8034e2957d34043b7a317a8a05d97dfe8fddb36d9a2252c0117dbbc"},
+ {file = "propcache-0.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ba68c57cde9c667f6b65b98bc342dfa7240b1272ffb2c24b32172ee61b6d281"},
+ {file = "propcache-0.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:eb77a85253174bf73e52c968b689d64be62d71e8ac33cabef4ca77b03fb4ef92"},
+ {file = "propcache-0.4.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c0e1c218fff95a66ad9f2f83ad41a67cf4d0a3f527efe820f57bde5fda616de4"},
+ {file = "propcache-0.4.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:5710b1c01472542bb024366803812ca13e8774d21381bcfc1f7ae738eeb38acc"},
+ {file = "propcache-0.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d7f008799682e8826ce98f25e8bc43532d2cd26c187a1462499fa8d123ae054f"},
+ {file = "propcache-0.4.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0596d2ae99d74ca436553eb9ce11fe4163dc742fcf8724ebe07d7cb0db679bb1"},
+ {file = "propcache-0.4.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab9c1bd95ebd1689f0e24f2946c495808777e9e8df7bb3c1dfe3e9eb7f47fe0d"},
+ {file = "propcache-0.4.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a8ef2ea819549ae2e8698d2ec229ae948d7272feea1cb2878289f767b6c585a4"},
+ {file = "propcache-0.4.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:71a400b2f0b079438cc24f9a27f02eff24d8ef78f2943f949abc518b844ade3d"},
+ {file = "propcache-0.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4c2735d3305e6cecab6e53546909edf407ad3da5b9eeaf483f4cf80142bb21be"},
+ {file = "propcache-0.4.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:72b51340047ac43b3cf388eebd362d052632260c9f73a50882edbb66e589fd44"},
+ {file = "propcache-0.4.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:184c779363740d6664982ad05699f378f7694220e2041996f12b7c2a4acdcad0"},
+ {file = "propcache-0.4.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a60634a9de41f363923c6adfb83105d39e49f7a3058511563ed3de6748661af6"},
+ {file = "propcache-0.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8119244d122241a9c4566bce49bb20408a6827044155856735cf14189a7da"},
+ {file = "propcache-0.4.0-cp313-cp313t-win32.whl", hash = "sha256:515b610a364c8cdd2b72c734cc97dece85c416892ea8d5c305624ac8734e81db"},
+ {file = "propcache-0.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:7ea86eb32e74f9902df57e8608e8ac66f1e1e1d24d1ed2ddeb849888413b924d"},
+ {file = "propcache-0.4.0-cp313-cp313t-win_arm64.whl", hash = "sha256:c1443fa4bb306461a3a8a52b7de0932a2515b100ecb0ebc630cc3f87d451e0a9"},
+ {file = "propcache-0.4.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:de8e310d24b5a61de08812dd70d5234da1458d41b059038ee7895a9e4c8cae79"},
+ {file = "propcache-0.4.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:55a54de5266bc44aa274915cdf388584fa052db8748a869e5500ab5993bac3f4"},
+ {file = "propcache-0.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:88d50d662c917ec2c9d3858920aa7b9d5bfb74ab9c51424b775ccbe683cb1b4e"},
+ {file = "propcache-0.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae3adf88a66f5863cf79394bc359da523bb27a2ed6ba9898525a6a02b723bfc5"},
+ {file = "propcache-0.4.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7f088e21d15b3abdb9047e4b7b7a0acd79bf166893ac2b34a72ab1062feb219e"},
+ {file = "propcache-0.4.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a4efbaf10793fd574c76a5732c75452f19d93df6e0f758c67dd60552ebd8614b"},
+ {file = "propcache-0.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:681a168d06284602d56e97f09978057aa88bcc4177352b875b3d781df4efd4cb"},
+ {file = "propcache-0.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a7f06f077fc4ef37e8a37ca6bbb491b29e29db9fb28e29cf3896aad10dbd4137"},
+ {file = "propcache-0.4.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:082a643479f49a6778dcd68a80262fc324b14fd8e9b1a5380331fe41adde1738"},
+ {file = "propcache-0.4.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:26692850120241a99bb4a4eec675cd7b4fdc431144f0d15ef69f7f8599f6165f"},
+ {file = "propcache-0.4.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:33ad7d37b9a386f97582f5d042cc7b8d4b3591bb384cf50866b749a17e4dba90"},
+ {file = "propcache-0.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e7fd82d4a5b7583588f103b0771e43948532f1292105f13ee6f3b300933c4ca"},
+ {file = "propcache-0.4.0-cp314-cp314-win32.whl", hash = "sha256:213eb0d3bc695a70cffffe11a1c2e1c2698d89ffd8dba35a49bc44a035d45c93"},
+ {file = "propcache-0.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:087e2d3d7613e1b59b2ffca0daabd500c1a032d189c65625ee05ea114afcad0b"},
+ {file = "propcache-0.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:94b0f7407d18001dbdcbb239512e753b1b36725a6e08a4983be1c948f5435f79"},
+ {file = "propcache-0.4.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b730048ae8b875e2c0af1a09ca31b303fc7b5ed27652beec03fa22b29545aec9"},
+ {file = "propcache-0.4.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f495007ada16a4e16312b502636fafff42a9003adf1d4fb7541e0a0870bc056f"},
+ {file = "propcache-0.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:659a0ea6d9017558ed7af00fb4028186f64d0ba9adfc70a4d2c85fcd3d026321"},
+ {file = "propcache-0.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d74aa60b1ec076d4d5dcde27c9a535fc0ebb12613f599681c438ca3daa68acac"},
+ {file = "propcache-0.4.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34000e31795bdcda9826e0e70e783847a42e3dcd0d6416c5d3cb717905ebaec0"},
+ {file = "propcache-0.4.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bcb5bfac5b9635e6fc520c8af6efc7a0a56f12a1fe9e9d3eb4328537e316dd6a"},
+ {file = "propcache-0.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ea11fceb31fa95b0fa2007037f19e922e2caceb7dc6c6cac4cb56e2d291f1a2"},
+ {file = "propcache-0.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:cd8684f628fe285ea5c86f88e1c30716239dc9d6ac55e7851a4b7f555b628da3"},
+ {file = "propcache-0.4.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:790286d3d542c0ef9f6d0280d1049378e5e776dcba780d169298f664c39394db"},
+ {file = "propcache-0.4.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:009093c9b5dbae114a5958e6a649f8a5d94dd6866b0f82b60395eb92c58002d4"},
+ {file = "propcache-0.4.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:728d98179e92d77096937fdfecd2c555a3d613abe56c9909165c24196a3b5012"},
+ {file = "propcache-0.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a9725d96a81e17e48a0fe82d0c3de2f5e623d7163fec70a6c7df90753edd1bec"},
+ {file = "propcache-0.4.0-cp314-cp314t-win32.whl", hash = "sha256:0964c55c95625193defeb4fd85f8f28a9a754ed012cab71127d10e3dc66b1373"},
+ {file = "propcache-0.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:24403152e41abf09488d3ae9c0c3bf7ff93e2fb12b435390718f21810353db28"},
+ {file = "propcache-0.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0363a696a9f24b37a04ed5e34c2e07ccbe92798c998d37729551120a1bb744c4"},
+ {file = "propcache-0.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0cd30341142c68377cf3c4e2d9f0581e6e528694b2d57c62c786be441053d2fc"},
+ {file = "propcache-0.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2c46d37955820dd883cf9156ceb7825b8903e910bdd869902e20a5ac4ecd2c8b"},
+ {file = "propcache-0.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0b12df77eb19266efd146627a65b8ad414f9d15672d253699a50c8205661a820"},
+ {file = "propcache-0.4.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1cdabd60e109506462e6a7b37008e57979e737dc6e7dfbe1437adcfe354d1a0a"},
+ {file = "propcache-0.4.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65ff56a31f25925ef030b494fe63289bf07ef0febe6da181b8219146c590e185"},
+ {file = "propcache-0.4.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:96153e037ae065bb71cae889f23c933190d81ae183f3696a030b47352fd8655d"},
+ {file = "propcache-0.4.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bf95be277fbb51513895c2cecc81ab12a421cdbd8837f159828a919a0167f96"},
+ {file = "propcache-0.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8d18d796ffecdc8253742fd53a94ceee2e77ad149eb9ed5960c2856b5f692f71"},
+ {file = "propcache-0.4.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4a52c25a51d5894ba60c567b0dbcf73de2f3cd642cf5343679e07ca3a768b085"},
+ {file = "propcache-0.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:e0ce7f3d1faf7ad58652ed758cc9753049af5308b38f89948aa71793282419c5"},
+ {file = "propcache-0.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:545987971b2aded25ba4698135ea0ae128836e7deb6e18c29a581076aaef44aa"},
+ {file = "propcache-0.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7da5c4c72ae40fd3ce87213ab057db66df53e55600d0b9e72e2b7f5a470a2cc4"},
+ {file = "propcache-0.4.0-cp39-cp39-win32.whl", hash = "sha256:2015218812ee8f13bbaebc9f52b1e424cc130b68d4857bef018e65e3834e1c4d"},
+ {file = "propcache-0.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:39f0f6a3b56e82dc91d84c763b783c5c33720a33c70ee48a1c13ba800ac1fa69"},
+ {file = "propcache-0.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:236c8da353ea7c22a8e963ab78cddb1126f700ae9538e2c4c6ef471e5545494b"},
+ {file = "propcache-0.4.0-py3-none-any.whl", hash = "sha256:015b2ca2f98ea9e08ac06eecc409d5d988f78c5fd5821b2ad42bc9afcd6b1557"},
+ {file = "propcache-0.4.0.tar.gz", hash = "sha256:c1ad731253eb738f9cadd9fa1844e019576c70bca6a534252e97cf33a57da529"},
+]
+
+[[package]]
+name = "psd-tools"
+version = "1.10.7"
+description = "Python package for working with Adobe Photoshop PSD files"
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "psd_tools-1.10.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9a1efd9f77d7b461ba2875cdb9dfbb9386f5d7971aa35fd7b4f727596a006e57"},
+ {file = "psd_tools-1.10.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08a193b4731bcf7bb6011b2ccbf7d6c0dec15e1771636a1762679520decae662"},
+ {file = "psd_tools-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2c4597b144cf040cc8430ef1c403fa01614a2da1fef25e6987a0b0ff908f47"},
+ {file = "psd_tools-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd19ab79a0e3d2abdb9df981a83da21dfe133fce911fff4a4dc7c45500f2f175"},
+ {file = "psd_tools-1.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae7863fdc5160b59b91d61890d3ecc36e9a5b68998e31acc7bbecd4f463c50e2"},
+ {file = "psd_tools-1.10.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:615a39df46893feb2d1bb9b895453289c3b89263da2e939a808794946800ae4b"},
+ {file = "psd_tools-1.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:30042b0e94d06c129f54f6464030290a64831a6e8be6d9d0864c39c60ca775fa"},
+ {file = "psd_tools-1.10.7-cp310-cp310-win32.whl", hash = "sha256:320da349491baf98d077ca508d51c600bb975052957398cef83abc59ee3b0723"},
+ {file = "psd_tools-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:9895d07ffb75349156537a666cbc606f163e19dd3d95951f73b8c90a6e16718e"},
+ {file = "psd_tools-1.10.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:027cd9b469319787e2e0a934e685f6542f11b476d0528a4da3ec87fc9b7db8a1"},
+ {file = "psd_tools-1.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:057d1ca344b4963d09f8027db09755fa20ebf76e2274f51f6f5b101a1d986034"},
+ {file = "psd_tools-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6507d7be5bd1aea8e41a6494f742b29ab8db081bf4b63662623213ee9e3ab58a"},
+ {file = "psd_tools-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e72bfb2534ddcdd964ac373ed594e81b75e1f1d6730cb41fd4196f4a0baa6546"},
+ {file = "psd_tools-1.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fcac33ff780a23bbe0fa1ffff301f3f2aa161ec0c684712213fb5542c88c85c9"},
+ {file = "psd_tools-1.10.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b60fa51566253b232aed67eccc0219f571244e94a326489c31facf55790aece"},
+ {file = "psd_tools-1.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:609eb3d97c1556c069c956dd6e09a4ed222466976b14316de06cb9f196d6039b"},
+ {file = "psd_tools-1.10.7-cp311-cp311-win32.whl", hash = "sha256:0f90ab4bac436af1ab14ddec21cbdb99c25ba8fbd1a3cf33805837ded418e8e6"},
+ {file = "psd_tools-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:1c8e16620252532795361a3063030ca2416ccb346c945d50374322c108bca75e"},
+ {file = "psd_tools-1.10.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:6949251c2c876a36d2197d02dfed8b31bc932ea6670f653e166781a6f3834642"},
+ {file = "psd_tools-1.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a86d6702540e9e4fccb79d0a48aba2ff92c430bc091a1cd8f9b41e593cdf402"},
+ {file = "psd_tools-1.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3120d5107d416d652576cbb6d154d1e2f4219d18587185a50f8bde9ad6678ba7"},
+ {file = "psd_tools-1.10.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d87edf8c436f4e0becfdeb4f3bdfc2f08494fa63835c5a605a8632877dbc0432"},
+ {file = "psd_tools-1.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c0b833fa1d491da47c5b10d81ce89b1cfd7967d18135ac27148b735932454d2d"},
+ {file = "psd_tools-1.10.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a276c2a1065c59fb87211c10cba73486aa637a90a6c55b3c6c2a8efa2ed2fc79"},
+ {file = "psd_tools-1.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cbc99ebb60d0658f5126c5ae4d104b2bea520b45ec3d5bbad5fd8c1a4c93c012"},
+ {file = "psd_tools-1.10.7-cp312-cp312-win32.whl", hash = "sha256:c1a47de3e074a5d6d3c921fa4e661d347e62aff46141f4bf4164d950f1553e3b"},
+ {file = "psd_tools-1.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:81c645312ea01fa7403da1cc2be3178e4a4c696e898bb2a9c91bac1c049d822d"},
+ {file = "psd_tools-1.10.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aea46c0c77bf66b8d0551a61dcd6a0902d66b4b1df04aedde2a8977d1755e84b"},
+ {file = "psd_tools-1.10.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bbd412c8739d81d1a98a03d534d22ab3178f12738a7e32826fd329c0e00daa9"},
+ {file = "psd_tools-1.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad441b03be77aa3136d42451a8eb93cd033adc0555ffc12b7823703dbed0e6ec"},
+ {file = "psd_tools-1.10.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddef5ade9863963031369c6ddd60b96985b0d6d4dd2859ea3e27562d99652138"},
+ {file = "psd_tools-1.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:de3acb63331cec373d1b41493dbde2fbbafd49aa1174f58c7dbac448cd9bab98"},
+ {file = "psd_tools-1.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8c2577413be84fcb9cceae45f1465e4b6373dec8c763310c22fefd004f760df"},
+ {file = "psd_tools-1.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f993011b8aee070996d32287a136c0e62c301372375d7354e54c165e88af3a2d"},
+ {file = "psd_tools-1.10.7-cp313-cp313-win32.whl", hash = "sha256:9e9294f654204a45a1067c67621304f26ec21fa6341500b55ecae6cb46715a92"},
+ {file = "psd_tools-1.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:2c1366ed301eb22d07e0edf9c19733f85234ca5b658724c6f550b83f3d10aa8b"},
+ {file = "psd_tools-1.10.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fc02714f18eec7c1de8cf09e21994f740ac18a50317be1d0c007535979962f5"},
+ {file = "psd_tools-1.10.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51d508d6ba6442f072db52083cb024f35a62dd4cecac602a154ddbd81d81d734"},
+ {file = "psd_tools-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0bb09c6c35f18dbd8189d6e31a901f0b1a517ad27f60a9deac11b99d5126e47"},
+ {file = "psd_tools-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58f06c838ff238717d7313f5b6df27b59040bdb3063300e79a7febd7ffdceba8"},
+ {file = "psd_tools-1.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0db6b955d76784847506a16877acd37afa479850d4de76448806cb98f8fd2d53"},
+ {file = "psd_tools-1.10.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fd299d0b437666b338abfc7576b715ce41a2f374c638d1045cf937b4460aa230"},
+ {file = "psd_tools-1.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:56b76bf86036cef0510181aac9c5c92e64cf758f1e6eefe7f79e6a5fe4e60a5f"},
+ {file = "psd_tools-1.10.7-cp39-cp39-win32.whl", hash = "sha256:b4fd98a7107f623b47eb9bcffa85b39e2d1a8a1972ef3a64cbca62adf9784d18"},
+ {file = "psd_tools-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d3565c8f6534f6f67860c60318e9934405d60e925e0453ad61a8582b81073045"},
+ {file = "psd_tools-1.10.7.tar.gz", hash = "sha256:af2a1ff338a8fc3e9a25bce8ec957a19e443d3b927b002f696e5ae9988d2978f"},
+]
+
+[package.dependencies]
+aggdraw = "*"
+attrs = ">=23.0.0"
+docopt = ">=0.6.0"
+numpy = "*"
+Pillow = ">=10.3.0"
+scikit-image = "*"
+scipy = "*"
+
+[package.extras]
+dev = ["ipython", "pytest", "pytest-cov", "ruff", "types-docopt"]
+docs = ["sphinx", "sphinx_rtd_theme"]
+
+[[package]]
+name = "ptyprocess"
+version = "0.7.0"
+description = "Run a subprocess in a pseudo terminal"
+optional = false
+python-versions = "*"
+groups = ["main", "dev"]
+markers = "sys_platform != \"win32\""
+files = [
+ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
+ {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
+]
+
+[[package]]
+name = "pyasn1"
+version = "0.6.1"
+description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"},
+ {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"},
+]
+
+[[package]]
+name = "pyasn1-modules"
+version = "0.4.2"
+description = "A collection of ASN.1-based protocols modules"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"},
+ {file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"},
+]
+
+[package.dependencies]
+pyasn1 = ">=0.6.1,<0.7.0"
+
+[[package]]
+name = "pycodestyle"
+version = "2.12.1"
+description = "Python style guide checker"
+optional = false
+python-versions = ">=3.8"
+groups = ["dev"]
+files = [
+ {file = "pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3"},
+ {file = "pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521"},
+]
+
+[[package]]
+name = "pycparser"
+version = "2.23"
+description = "C parser in Python"
+optional = false
+python-versions = ">=3.8"
+groups = ["main", "dev"]
+files = [
+ {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"},
+ {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"},
+]
+markers = {main = "implementation_name == \"pypy\" or platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"", dev = "implementation_name == \"pypy\""}
+
+[[package]]
+name = "pydevd"
+version = "3.3.0"
+description = "PyDev.Debugger (used in PyDev, PyCharm and VSCode Python)"
+optional = false
+python-versions = "*"
+groups = ["dev"]
+files = [
+ {file = "pydevd-3.3.0-cp310-cp310-macosx_14_0_universal2.whl", hash = "sha256:5a3a6948d09db219754efdd254fb462aa68a76e635cabc9cb7e95669ce161b14"},
+ {file = "pydevd-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04fad1696d596e7bc0e938ca6a08bc0abcc9f6e10099b67148c9fe8abdddf36a"},
+ {file = "pydevd-3.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aadeec65b783264cc162426e97d3fe967ca2bf742b4cfef362562ca8cd75b829"},
+ {file = "pydevd-3.3.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6221258670994bddbfcf1c878ee40485cdda56dc47f95024c0050248c0023e66"},
+ {file = "pydevd-3.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:65044faa27b8ce5f3166ad0bfcd080983aa5244af130f98aa81eab509b3a072d"},
+ {file = "pydevd-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fdfef7091745a495341d6fe3c74ff6c6031e1fde0495a49c6887600dddc80ab9"},
+ {file = "pydevd-3.3.0-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:46d7438e74c5903ae6ac1cc824cc7df1597f26929ee95379396aa0dd963625d0"},
+ {file = "pydevd-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad52f71503825b571fdb00afbec6c9e9989c634b8a8d901e343b56f858b70a49"},
+ {file = "pydevd-3.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925dc3f884832d58d241c6f9275cfaf5e8fd1f328a54642d2c601e2c106c1277"},
+ {file = "pydevd-3.3.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:794cd4c20ff8d23c42e44ca69b038e60043d83d6b6cce2ff4e55dd3964679507"},
+ {file = "pydevd-3.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1472dd4ca78c2d5c3b0b165d7f0c9b00b523b3a1d059dbdfe22c75f1a42c34e5"},
+ {file = "pydevd-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:cb190421435f56b8366a2757281962a8dca31c6ea480cd5e213e24d6418a809c"},
+ {file = "pydevd-3.3.0-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:2a47457fd0b45666fbe76b5037c4b4a2c5c9fc87755faf6c8d47accc7d0e4dc6"},
+ {file = "pydevd-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c67695b446014c3e893e2443dfc00abf1c1f25983148fa7899c21f32f70428"},
+ {file = "pydevd-3.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47737ab44b3365a741ee9e57d43951d7067938169411785cf2d7507cd049869a"},
+ {file = "pydevd-3.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1a2fa54ee2be7dc19c220e113551c92199c152a4ee348e7c3c105ebc7cff623c"},
+ {file = "pydevd-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e0490b1d6aa50c0b0b54166ef9605c837411f0134b97e5afa6686f31eba1d830"},
+ {file = "pydevd-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:c027d2249478d127a146f245d50de9a211296467ec9d21f25febf3ac916623da"},
+ {file = "pydevd-3.3.0-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:21506d009947e4766953ee80ae2b7806bb8144d9da2151408a60e727e19dcf24"},
+ {file = "pydevd-3.3.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a779970f39580a84e48aec5ad1cd60ad59c5e7b820d31dae058427fb71a8747"},
+ {file = "pydevd-3.3.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206232066a737bdc1ea27e46a61356a8b0cfdbfd3befe667aed2ba267102f72b"},
+ {file = "pydevd-3.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8f61b3fbc1b1da52bd16289cf89f7b621c28787e3a6134285d85d79aa43d6fcb"},
+ {file = "pydevd-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cc982957d6c75fe42c14a15793ce812a5acc6a4f9baf88785d150a4cdc267b0"},
+ {file = "pydevd-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:77d5e8688ddca31a8d342baf3d37b39db3c6c5e639f65f66ae58b9bc6dc47637"},
+ {file = "pydevd-3.3.0-cp38-cp38-macosx_14_0_universal2.whl", hash = "sha256:22f0d5f5347e44469ac46cb7bbd8817f7b44754e755e4d770dce13aa26a0aaf4"},
+ {file = "pydevd-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acdf76c291ecca0121d5fd8e631246865cf604356c2fb354da9f446ed6cdf17d"},
+ {file = "pydevd-3.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce504ee65acca6ed1ccc6e39cc3cf48ada01a318628cc8743fe7dc07e05ebc7a"},
+ {file = "pydevd-3.3.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ccbd7a2a74e3b04079fec0eb3e3633cdf15c75eeab0a0dcca3be23c87a13f7f1"},
+ {file = "pydevd-3.3.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:07d0a52e73fb8d6de1449178d0ae6a54acc1234834fb76811eb55e14c73d26f1"},
+ {file = "pydevd-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:10d549260fde494664255ef5e245e204fc6c0827f4ba3d486e7f54d202912367"},
+ {file = "pydevd-3.3.0-cp39-cp39-macosx_14_0_universal2.whl", hash = "sha256:79c4752d9794b583ee775c1e40d868b567bc79c05b89a58aefc9c8e5c3719976"},
+ {file = "pydevd-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7c6b3e34e3b0d8952addc58dcb2aaeb9c8b92a51c7255d3e11356ac7d195594"},
+ {file = "pydevd-3.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15527e3b42a90d2b9ca568ef506ee3d0b0f3ebf5770bdc036916b61b2480f253"},
+ {file = "pydevd-3.3.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:150ff02deac2a49a0f3b352766789fdf7313281aafdb78840b11413fbc2ac06e"},
+ {file = "pydevd-3.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:512250f1100f361ca7e3a0b0da30b3f2876cb3ca1747deab32c0f5e4c3cd0df4"},
+ {file = "pydevd-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:29ae2c91f5d9ebb080d64e7f2cb5d127ccbfbee2edd34cbce90db61ac07647b2"},
+ {file = "pydevd-3.3.0.tar.gz", hash = "sha256:aa4bdb74c5e21bde8f396c5055f5e34b0a23a359ec1cc44c6b25282adc9c3f50"},
+]
+
+[[package]]
+name = "pyflakes"
+version = "3.2.0"
+description = "passive checker of Python programs"
+optional = false
+python-versions = ">=3.8"
+groups = ["dev"]
+files = [
+ {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"},
+ {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"},
+]
+
+[[package]]
+name = "pygments"
+version = "2.19.1"
+description = "Pygments is a syntax highlighting package written in Python."
+optional = false
+python-versions = ">=3.8"
+groups = ["main", "dev", "docs"]
+files = [
+ {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"},
+ {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"},
+]
+
+[package.extras]
+windows-terminal = ["colorama (>=0.4.6)"]
+
+[[package]]
+name = "pyjwe"
+version = "1.0.0"
+description = "JSON Web Encryption implementation in Python"
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "PyJWE-1.0.0.tar.gz", hash = "sha256:e3b3de7be4fcc260e5f1a47ead9c9a9211d8ce98f9e1d88d9a7225198aa9ce47"},
+]
+
+[package.dependencies]
+cryptography = ">=0.9.3"
+
+[[package]]
+name = "pyjwt"
+version = "2.10.1"
+description = "JSON Web Token implementation in Python"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"},
+ {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"},
+]
+
+[package.extras]
+crypto = ["cryptography (>=3.4.0)"]
+dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"]
+docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
+tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
+
+[[package]]
+name = "pyreadline3"
+version = "3.5.4"
+description = "A python implementation of GNU readline."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+markers = "sys_platform == \"win32\""
+files = [
+ {file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"},
+ {file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"},
+]
+
+[package.extras]
+dev = ["build", "flake8", "mypy", "pytest", "twine"]
+
+[[package]]
+name = "pytest"
+version = "8.1.1"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.8"
+groups = ["dev"]
+files = [
+ {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
+ {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=1.4,<2.0"
+
+[package.extras]
+testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+
+[[package]]
+name = "pytest-cov"
+version = "4.1.0"
+description = "Pytest plugin for measuring coverage."
+optional = false
+python-versions = ">=3.7"
+groups = ["dev"]
+files = [
+ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
+ {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
+]
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0"
+description = "Extensions to the standard Python datetime module"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+groups = ["main"]
+files = [
+ {file = "python-dateutil-2.9.0.tar.gz", hash = "sha256:78e73e19c63f5b20ffa567001531680d939dc042bf7850431877645523c66709"},
+ {file = "python_dateutil-2.9.0-py2.py3-none-any.whl", hash = "sha256:cbf2f1da5e6083ac2fbfd4da39a25f34312230110440f424a14c7558bb85d82e"},
+]
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+name = "pytokens"
+version = "0.1.10"
+description = "A Fast, spec compliant Python 3.12+ tokenizer that runs on older Pythons."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "pytokens-0.1.10-py3-none-any.whl", hash = "sha256:db7b72284e480e69fb085d9f251f66b3d2df8b7166059261258ff35f50fb711b"},
+ {file = "pytokens-0.1.10.tar.gz", hash = "sha256:c9a4bfa0be1d26aebce03e6884ba454e842f186a59ea43a6d3b25af58223c044"},
+]
+
+[package.extras]
+dev = ["black", "build", "mypy", "pytest", "pytest-cov", "setuptools", "tox", "twine", "wheel"]
+
+[[package]]
+name = "pytz"
+version = "2025.1"
+description = "World timezone definitions, modern and historical"
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57"},
+ {file = "pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e"},
+]
+
+[[package]]
+name = "pywin32"
+version = "311"
+description = "Python for Window Extensions"
+optional = false
+python-versions = "*"
+groups = ["main"]
+markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""
+files = [
+ {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"},
+ {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"},
+ {file = "pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b"},
+ {file = "pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151"},
+ {file = "pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503"},
+ {file = "pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2"},
+ {file = "pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31"},
+ {file = "pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067"},
+ {file = "pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852"},
+ {file = "pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d"},
+ {file = "pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d"},
+ {file = "pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a"},
+ {file = "pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee"},
+ {file = "pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87"},
+ {file = "pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42"},
+ {file = "pywin32-311-cp38-cp38-win32.whl", hash = "sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c"},
+ {file = "pywin32-311-cp38-cp38-win_amd64.whl", hash = "sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd"},
+ {file = "pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b"},
+ {file = "pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91"},
+ {file = "pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d"},
+]
+
+[[package]]
+name = "pyzmq"
+version = "26.2.1"
+description = "Python bindings for 0MQ"
+optional = false
+python-versions = ">=3.7"
+groups = ["main", "dev"]
+files = [
+ {file = "pyzmq-26.2.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:f39d1227e8256d19899d953e6e19ed2ccb689102e6d85e024da5acf410f301eb"},
+ {file = "pyzmq-26.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a23948554c692df95daed595fdd3b76b420a4939d7a8a28d6d7dea9711878641"},
+ {file = "pyzmq-26.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95f5728b367a042df146cec4340d75359ec6237beebf4a8f5cf74657c65b9257"},
+ {file = "pyzmq-26.2.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95f7b01b3f275504011cf4cf21c6b885c8d627ce0867a7e83af1382ebab7b3ff"},
+ {file = "pyzmq-26.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80a00370a2ef2159c310e662c7c0f2d030f437f35f478bb8b2f70abd07e26b24"},
+ {file = "pyzmq-26.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8531ed35dfd1dd2af95f5d02afd6545e8650eedbf8c3d244a554cf47d8924459"},
+ {file = "pyzmq-26.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cdb69710e462a38e6039cf17259d328f86383a06c20482cc154327968712273c"},
+ {file = "pyzmq-26.2.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e7eeaef81530d0b74ad0d29eec9997f1c9230c2f27242b8d17e0ee67662c8f6e"},
+ {file = "pyzmq-26.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:361edfa350e3be1f987e592e834594422338d7174364763b7d3de5b0995b16f3"},
+ {file = "pyzmq-26.2.1-cp310-cp310-win32.whl", hash = "sha256:637536c07d2fb6a354988b2dd1d00d02eb5dd443f4bbee021ba30881af1c28aa"},
+ {file = "pyzmq-26.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:45fad32448fd214fbe60030aa92f97e64a7140b624290834cc9b27b3a11f9473"},
+ {file = "pyzmq-26.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:d9da0289d8201c8a29fd158aaa0dfe2f2e14a181fd45e2dc1fbf969a62c1d594"},
+ {file = "pyzmq-26.2.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:c059883840e634a21c5b31d9b9a0e2b48f991b94d60a811092bc37992715146a"},
+ {file = "pyzmq-26.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ed038a921df836d2f538e509a59cb638df3e70ca0fcd70d0bf389dfcdf784d2a"},
+ {file = "pyzmq-26.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9027a7fcf690f1a3635dc9e55e38a0d6602dbbc0548935d08d46d2e7ec91f454"},
+ {file = "pyzmq-26.2.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d75fcb00a1537f8b0c0bb05322bc7e35966148ffc3e0362f0369e44a4a1de99"},
+ {file = "pyzmq-26.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0019cc804ac667fb8c8eaecdb66e6d4a68acf2e155d5c7d6381a5645bd93ae4"},
+ {file = "pyzmq-26.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:f19dae58b616ac56b96f2e2290f2d18730a898a171f447f491cc059b073ca1fa"},
+ {file = "pyzmq-26.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f5eeeb82feec1fc5cbafa5ee9022e87ffdb3a8c48afa035b356fcd20fc7f533f"},
+ {file = "pyzmq-26.2.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:000760e374d6f9d1a3478a42ed0c98604de68c9e94507e5452951e598ebecfba"},
+ {file = "pyzmq-26.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:817fcd3344d2a0b28622722b98500ae9c8bfee0f825b8450932ff19c0b15bebd"},
+ {file = "pyzmq-26.2.1-cp311-cp311-win32.whl", hash = "sha256:88812b3b257f80444a986b3596e5ea5c4d4ed4276d2b85c153a6fbc5ca457ae7"},
+ {file = "pyzmq-26.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:ef29630fde6022471d287c15c0a2484aba188adbfb978702624ba7a54ddfa6c1"},
+ {file = "pyzmq-26.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:f32718ee37c07932cc336096dc7403525301fd626349b6eff8470fe0f996d8d7"},
+ {file = "pyzmq-26.2.1-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:a6549ecb0041dafa55b5932dcbb6c68293e0bd5980b5b99f5ebb05f9a3b8a8f3"},
+ {file = "pyzmq-26.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0250c94561f388db51fd0213cdccbd0b9ef50fd3c57ce1ac937bf3034d92d72e"},
+ {file = "pyzmq-26.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ee4297d9e4b34b5dc1dd7ab5d5ea2cbba8511517ef44104d2915a917a56dc8"},
+ {file = "pyzmq-26.2.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2a9cb17fd83b7a3a3009901aca828feaf20aa2451a8a487b035455a86549c09"},
+ {file = "pyzmq-26.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:786dd8a81b969c2081b31b17b326d3a499ddd1856e06d6d79ad41011a25148da"},
+ {file = "pyzmq-26.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:2d88ba221a07fc2c5581565f1d0fe8038c15711ae79b80d9462e080a1ac30435"},
+ {file = "pyzmq-26.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c84c1297ff9f1cd2440da4d57237cb74be21fdfe7d01a10810acba04e79371a"},
+ {file = "pyzmq-26.2.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:46d4ebafc27081a7f73a0f151d0c38d4291656aa134344ec1f3d0199ebfbb6d4"},
+ {file = "pyzmq-26.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:91e2bfb8e9a29f709d51b208dd5f441dc98eb412c8fe75c24ea464734ccdb48e"},
+ {file = "pyzmq-26.2.1-cp312-cp312-win32.whl", hash = "sha256:4a98898fdce380c51cc3e38ebc9aa33ae1e078193f4dc641c047f88b8c690c9a"},
+ {file = "pyzmq-26.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:a0741edbd0adfe5f30bba6c5223b78c131b5aa4a00a223d631e5ef36e26e6d13"},
+ {file = "pyzmq-26.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:e5e33b1491555843ba98d5209439500556ef55b6ab635f3a01148545498355e5"},
+ {file = "pyzmq-26.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:099b56ef464bc355b14381f13355542e452619abb4c1e57a534b15a106bf8e23"},
+ {file = "pyzmq-26.2.1-cp313-cp313-macosx_10_15_universal2.whl", hash = "sha256:651726f37fcbce9f8dd2a6dab0f024807929780621890a4dc0c75432636871be"},
+ {file = "pyzmq-26.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57dd4d91b38fa4348e237a9388b4423b24ce9c1695bbd4ba5a3eada491e09399"},
+ {file = "pyzmq-26.2.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d51a7bfe01a48e1064131f3416a5439872c533d756396be2b39e3977b41430f9"},
+ {file = "pyzmq-26.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7154d228502e18f30f150b7ce94f0789d6b689f75261b623f0fdc1eec642aab"},
+ {file = "pyzmq-26.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:f1f31661a80cc46aba381bed475a9135b213ba23ca7ff6797251af31510920ce"},
+ {file = "pyzmq-26.2.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:290c96f479504439b6129a94cefd67a174b68ace8a8e3f551b2239a64cfa131a"},
+ {file = "pyzmq-26.2.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:f2c307fbe86e18ab3c885b7e01de942145f539165c3360e2af0f094dd440acd9"},
+ {file = "pyzmq-26.2.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:b314268e716487bfb86fcd6f84ebbe3e5bec5fac75fdf42bc7d90fdb33f618ad"},
+ {file = "pyzmq-26.2.1-cp313-cp313-win32.whl", hash = "sha256:edb550616f567cd5603b53bb52a5f842c0171b78852e6fc7e392b02c2a1504bb"},
+ {file = "pyzmq-26.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:100a826a029c8ef3d77a1d4c97cbd6e867057b5806a7276f2bac1179f893d3bf"},
+ {file = "pyzmq-26.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:6991ee6c43e0480deb1b45d0c7c2bac124a6540cba7db4c36345e8e092da47ce"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:25e720dba5b3a3bb2ad0ad5d33440babd1b03438a7a5220511d0c8fa677e102e"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:9ec6abfb701437142ce9544bd6a236addaf803a32628d2260eb3dbd9a60e2891"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e1eb9d2bfdf5b4e21165b553a81b2c3bd5be06eeddcc4e08e9692156d21f1f6"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90dc731d8e3e91bcd456aa7407d2eba7ac6f7860e89f3766baabb521f2c1de4a"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6a93d684278ad865fc0b9e89fe33f6ea72d36da0e842143891278ff7fd89c3"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:c1bb37849e2294d519117dd99b613c5177934e5c04a5bb05dd573fa42026567e"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:632a09c6d8af17b678d84df442e9c3ad8e4949c109e48a72f805b22506c4afa7"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:fc409c18884eaf9ddde516d53af4f2db64a8bc7d81b1a0c274b8aa4e929958e8"},
+ {file = "pyzmq-26.2.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:17f88622b848805d3f6427ce1ad5a2aa3cf61f12a97e684dab2979802024d460"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3ef584f13820d2629326fe20cc04069c21c5557d84c26e277cfa6235e523b10f"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:160194d1034902937359c26ccfa4e276abffc94937e73add99d9471e9f555dd6"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:574b285150afdbf0a0424dddf7ef9a0d183988eb8d22feacb7160f7515e032cb"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44dba28c34ce527cf687156c81f82bf1e51f047838d5964f6840fd87dfecf9fe"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9fbdb90b85c7624c304f72ec7854659a3bd901e1c0ffb2363163779181edeb68"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a7ad34a2921e8f76716dc7205c9bf46a53817e22b9eec2e8a3e08ee4f4a72468"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:866c12b7c90dd3a86983df7855c6f12f9407c8684db6aa3890fc8027462bda82"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-win32.whl", hash = "sha256:eeb37f65350d5c5870517f02f8bbb2ac0fbec7b416c0f4875219fef305a89a45"},
+ {file = "pyzmq-26.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4eb3197f694dfb0ee6af29ef14a35f30ae94ff67c02076eef8125e2d98963cd0"},
+ {file = "pyzmq-26.2.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:36d4e7307db7c847fe37413f333027d31c11d5e6b3bacbb5022661ac635942ba"},
+ {file = "pyzmq-26.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1c6ae0e95d0a4b0cfe30f648a18e764352d5415279bdf34424decb33e79935b8"},
+ {file = "pyzmq-26.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5b4fc44f5360784cc02392f14235049665caaf7c0fe0b04d313e763d3338e463"},
+ {file = "pyzmq-26.2.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:51431f6b2750eb9b9d2b2952d3cc9b15d0215e1b8f37b7a3239744d9b487325d"},
+ {file = "pyzmq-26.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdbc78ae2065042de48a65f1421b8af6b76a0386bb487b41955818c3c1ce7bed"},
+ {file = "pyzmq-26.2.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d14f50d61a89b0925e4d97a0beba6053eb98c426c5815d949a43544f05a0c7ec"},
+ {file = "pyzmq-26.2.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:004837cb958988c75d8042f5dac19a881f3d9b3b75b2f574055e22573745f841"},
+ {file = "pyzmq-26.2.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b2007f28ce1b8acebdf4812c1aab997a22e57d6a73b5f318b708ef9bcabbe95"},
+ {file = "pyzmq-26.2.1-cp38-cp38-win32.whl", hash = "sha256:269c14904da971cb5f013100d1aaedb27c0a246728c341d5d61ddd03f463f2f3"},
+ {file = "pyzmq-26.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:31fff709fef3b991cfe7189d2cfe0c413a1d0e82800a182cfa0c2e3668cd450f"},
+ {file = "pyzmq-26.2.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:a4bffcadfd40660f26d1b3315a6029fd4f8f5bf31a74160b151f5c577b2dc81b"},
+ {file = "pyzmq-26.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e76ad4729c2f1cf74b6eb1bdd05f6aba6175999340bd51e6caee49a435a13bf5"},
+ {file = "pyzmq-26.2.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8b0f5bab40a16e708e78a0c6ee2425d27e1a5d8135c7a203b4e977cee37eb4aa"},
+ {file = "pyzmq-26.2.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e8e47050412f0ad3a9b2287779758073cbf10e460d9f345002d4779e43bb0136"},
+ {file = "pyzmq-26.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f18ce33f422d119b13c1363ed4cce245b342b2c5cbbb76753eabf6aa6f69c7d"},
+ {file = "pyzmq-26.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ceb0d78b7ef106708a7e2c2914afe68efffc0051dc6a731b0dbacd8b4aee6d68"},
+ {file = "pyzmq-26.2.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ebdd96bd637fd426d60e86a29ec14b8c1ab64b8d972f6a020baf08a30d1cf46"},
+ {file = "pyzmq-26.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:03719e424150c6395b9513f53a5faadcc1ce4b92abdf68987f55900462ac7eec"},
+ {file = "pyzmq-26.2.1-cp39-cp39-win32.whl", hash = "sha256:ef5479fac31df4b304e96400fc67ff08231873ee3537544aa08c30f9d22fce38"},
+ {file = "pyzmq-26.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:f92a002462154c176dac63a8f1f6582ab56eb394ef4914d65a9417f5d9fde218"},
+ {file = "pyzmq-26.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:1fd4b3efc6f62199886440d5e27dd3ccbcb98dfddf330e7396f1ff421bfbb3c2"},
+ {file = "pyzmq-26.2.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:380816d298aed32b1a97b4973a4865ef3be402a2e760204509b52b6de79d755d"},
+ {file = "pyzmq-26.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97cbb368fd0debdbeb6ba5966aa28e9a1ae3396c7386d15569a6ca4be4572b99"},
+ {file = "pyzmq-26.2.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf7b5942c6b0dafcc2823ddd9154f419147e24f8df5b41ca8ea40a6db90615c"},
+ {file = "pyzmq-26.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fe6e28a8856aea808715f7a4fc11f682b9d29cac5d6262dd8fe4f98edc12d53"},
+ {file = "pyzmq-26.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bd8fdee945b877aa3bffc6a5a8816deb048dab0544f9df3731ecd0e54d8c84c9"},
+ {file = "pyzmq-26.2.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ee7152f32c88e0e1b5b17beb9f0e2b14454235795ef68c0c120b6d3d23d12833"},
+ {file = "pyzmq-26.2.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:baa1da72aecf6a490b51fba7a51f1ce298a1e0e86d0daef8265c8f8f9848eb77"},
+ {file = "pyzmq-26.2.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:49135bb327fca159262d8fd14aa1f4a919fe071b04ed08db4c7c37d2f0647162"},
+ {file = "pyzmq-26.2.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8bacc1a10c150d58e8a9ee2b2037a70f8d903107e0f0b6e079bf494f2d09c091"},
+ {file = "pyzmq-26.2.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:09dac387ce62d69bec3f06d51610ca1d660e7849eb45f68e38e7f5cf1f49cbcb"},
+ {file = "pyzmq-26.2.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:70b3a46ecd9296e725ccafc17d732bfc3cdab850b54bd913f843a0a54dfb2c04"},
+ {file = "pyzmq-26.2.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:59660e15c797a3b7a571c39f8e0b62a1f385f98ae277dfe95ca7eaf05b5a0f12"},
+ {file = "pyzmq-26.2.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0f50db737d688e96ad2a083ad2b453e22865e7e19c7f17d17df416e91ddf67eb"},
+ {file = "pyzmq-26.2.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a003200b6cd64e89b5725ff7e284a93ab24fd54bbac8b4fa46b1ed57be693c27"},
+ {file = "pyzmq-26.2.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f9ba5def063243793dec6603ad1392f735255cbc7202a3a484c14f99ec290705"},
+ {file = "pyzmq-26.2.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1238c2448c58b9c8d6565579393148414a42488a5f916b3f322742e561f6ae0d"},
+ {file = "pyzmq-26.2.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8eddb3784aed95d07065bcf94d07e8c04024fdb6b2386f08c197dfe6b3528fda"},
+ {file = "pyzmq-26.2.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0f19c2097fffb1d5b07893d75c9ee693e9cbc809235cf3f2267f0ef6b015f24"},
+ {file = "pyzmq-26.2.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0995fd3530f2e89d6b69a2202e340bbada3191014352af978fa795cb7a446331"},
+ {file = "pyzmq-26.2.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7c6160fe513654e65665332740f63de29ce0d165e053c0c14a161fa60dd0da01"},
+ {file = "pyzmq-26.2.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8ec8e3aea6146b761d6c57fcf8f81fcb19f187afecc19bf1701a48db9617a217"},
+ {file = "pyzmq-26.2.1.tar.gz", hash = "sha256:17d72a74e5e9ff3829deb72897a175333d3ef5b5413948cae3cf7ebf0b02ecca"},
+]
+
+[package.dependencies]
+cffi = {version = "*", markers = "implementation_name == \"pypy\""}
+
+[[package]]
+name = "redis"
+version = "5.2.1"
+description = "Python client for Redis database and key-value store"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4"},
+ {file = "redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f"},
+]
+
+[package.extras]
+hiredis = ["hiredis (>=3.0.0)"]
+ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==23.2.1)", "requests (>=2.31.0)"]
+
+[[package]]
+name = "referencing"
+version = "0.36.2"
+description = "JSON Referencing + Python"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"},
+ {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+rpds-py = ">=0.7.0"
+
+[[package]]
+name = "reportlab"
+version = "4.4.0"
+description = "The Reportlab Toolkit"
+optional = false
+python-versions = "<4,>=3.7"
+groups = ["main"]
+files = [
+ {file = "reportlab-4.4.0-py3-none-any.whl", hash = "sha256:0a993f1d4a765fcbdf4e26adc96b3351004ebf4d27583340595ba7edafebec32"},
+ {file = "reportlab-4.4.0.tar.gz", hash = "sha256:a64d85513910e246c21dc97ccc3c9054a1d44370bf8fc1fab80af937814354d5"},
+]
+
+[package.dependencies]
+chardet = "*"
+pillow = ">=9.0.0"
+
+[package.extras]
+accel = ["rl_accel (>=0.9.0,<1.1)"]
+bidi = ["rlbidi"]
+pycairo = ["freetype-py (>=2.3.0,<2.4)", "rlPyCairo (>=0.2.0,<1)"]
+renderpm = ["rl_renderPM (>=4.0.3,<4.1)"]
+shaping = ["uharfbuzz"]
+
+[[package]]
+name = "requests"
+version = "2.32.5"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.9"
+groups = ["dev", "docs"]
+files = [
+ {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"},
+ {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset_normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "roman-numerals-py"
+version = "3.1.0"
+description = "Manipulate well-formed Roman numerals"
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c"},
+ {file = "roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d"},
+]
+
+[package.extras]
+lint = ["mypy (==1.15.0)", "pyright (==1.1.394)", "ruff (==0.9.7)"]
+test = ["pytest (>=8)"]
+
+[[package]]
+name = "rpds-py"
+version = "0.27.1"
+description = "Python bindings to Rust's persistent data structures (rpds)"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef"},
+ {file = "rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9024de74731df54546fab0bfbcdb49fae19159ecaecfc8f37c18d2c7e2c0bd61"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31d3ebadefcd73b73928ed0b2fd696f7fefda8629229f81929ac9c1854d0cffb"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2e7f8f169d775dd9092a1743768d771f1d1300453ddfe6325ae3ab5332b4657"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d905d16f77eb6ab2e324e09bfa277b4c8e5e6b8a78a3e7ff8f3cdf773b4c013"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50c946f048209e6362e22576baea09193809f87687a95a8db24e5fbdb307b93a"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:3deab27804d65cd8289eb814c2c0e807c4b9d9916c9225e363cb0cf875eb67c1"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b61097f7488de4be8244c89915da8ed212832ccf1e7c7753a25a394bf9b1f10"},
+ {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a3f29aba6e2d7d90528d3c792555a93497fe6538aa65eb675b44505be747808"},
+ {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd6cd0485b7d347304067153a6dc1d73f7d4fd995a396ef32a24d24b8ac63ac8"},
+ {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f4461bf931108c9fa226ffb0e257c1b18dc2d44cd72b125bec50ee0ab1248a9"},
+ {file = "rpds_py-0.27.1-cp310-cp310-win32.whl", hash = "sha256:ee5422d7fb21f6a00c1901bf6559c49fee13a5159d0288320737bbf6585bd3e4"},
+ {file = "rpds_py-0.27.1-cp310-cp310-win_amd64.whl", hash = "sha256:3e039aabf6d5f83c745d5f9a0a381d031e9ed871967c0a5c38d201aca41f3ba1"},
+ {file = "rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881"},
+ {file = "rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde"},
+ {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21"},
+ {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9"},
+ {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948"},
+ {file = "rpds_py-0.27.1-cp311-cp311-win32.whl", hash = "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39"},
+ {file = "rpds_py-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15"},
+ {file = "rpds_py-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746"},
+ {file = "rpds_py-0.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90"},
+ {file = "rpds_py-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444"},
+ {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a"},
+ {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1"},
+ {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998"},
+ {file = "rpds_py-0.27.1-cp312-cp312-win32.whl", hash = "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39"},
+ {file = "rpds_py-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594"},
+ {file = "rpds_py-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502"},
+ {file = "rpds_py-0.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b"},
+ {file = "rpds_py-0.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274"},
+ {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd"},
+ {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2"},
+ {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002"},
+ {file = "rpds_py-0.27.1-cp313-cp313-win32.whl", hash = "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3"},
+ {file = "rpds_py-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83"},
+ {file = "rpds_py-0.27.1-cp313-cp313-win_arm64.whl", hash = "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-win32.whl", hash = "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-win_amd64.whl", hash = "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797"},
+ {file = "rpds_py-0.27.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334"},
+ {file = "rpds_py-0.27.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60"},
+ {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e"},
+ {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212"},
+ {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675"},
+ {file = "rpds_py-0.27.1-cp314-cp314-win32.whl", hash = "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3"},
+ {file = "rpds_py-0.27.1-cp314-cp314-win_amd64.whl", hash = "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456"},
+ {file = "rpds_py-0.27.1-cp314-cp314-win_arm64.whl", hash = "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772"},
+ {file = "rpds_py-0.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c918c65ec2e42c2a78d19f18c553d77319119bf43aa9e2edf7fb78d624355527"},
+ {file = "rpds_py-0.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fea2b1a922c47c51fd07d656324531adc787e415c8b116530a1d29c0516c62d"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbf94c58e8e0cd6b6f38d8de67acae41b3a515c26169366ab58bdca4a6883bb8"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c2a8fed130ce946d5c585eddc7c8eeef0051f58ac80a8ee43bd17835c144c2cc"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:037a2361db72ee98d829bc2c5b7cc55598ae0a5e0ec1823a56ea99374cfd73c1"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5281ed1cc1d49882f9997981c88df1a22e140ab41df19071222f7e5fc4e72125"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd50659a069c15eef8aa3d64bbef0d69fd27bb4a50c9ab4f17f83a16cbf8905"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:c4b676c4ae3921649a15d28ed10025548e9b561ded473aa413af749503c6737e"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:079bc583a26db831a985c5257797b2b5d3affb0386e7ff886256762f82113b5e"},
+ {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4e44099bd522cba71a2c6b97f68e19f40e7d85399de899d66cdb67b32d7cb786"},
+ {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e202e6d4188e53c6661af813b46c37ca2c45e497fc558bacc1a7630ec2695aec"},
+ {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f41f814b8eaa48768d1bb551591f6ba45f87ac76899453e8ccd41dba1289b04b"},
+ {file = "rpds_py-0.27.1-cp39-cp39-win32.whl", hash = "sha256:9e71f5a087ead99563c11fdaceee83ee982fd39cf67601f4fd66cb386336ee52"},
+ {file = "rpds_py-0.27.1-cp39-cp39-win_amd64.whl", hash = "sha256:71108900c9c3c8590697244b9519017a400d9ba26a36c48381b3f64743a44aab"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7ba22cb9693df986033b91ae1d7a979bc399237d45fccf875b76f62bb9e52ddf"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b640501be9288c77738b5492b3fd3abc4ba95c50c2e41273c8a1459f08298d3"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb08b65b93e0c6dd70aac7f7890a9c0938d5ec71d5cb32d45cf844fb8ae47636"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d7ff07d696a7a38152ebdb8212ca9e5baab56656749f3d6004b34ab726b550b8"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb7c72262deae25366e3b6c0c0ba46007967aea15d1eea746e44ddba8ec58dcc"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b002cab05d6339716b03a4a3a2ce26737f6231d7b523f339fa061d53368c9d8"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23f6b69d1c26c4704fec01311963a41d7de3ee0570a84ebde4d544e5a1859ffc"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:530064db9146b247351f2a0250b8f00b289accea4596a033e94be2389977de71"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b90b0496570bd6b0321724a330d8b545827c4df2034b6ddfc5f5275f55da2ad"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879b0e14a2da6a1102a3fc8af580fc1ead37e6d6692a781bd8c83da37429b5ab"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:0d807710df3b5faa66c731afa162ea29717ab3be17bdc15f90f2d9f183da4059"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3adc388fc3afb6540aec081fa59e6e0d3908722771aa1e37ffe22b220a436f0b"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c796c0c1cc68cb08b0284db4229f5af76168172670c74908fdbd4b7d7f515819"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa8933159edc50be265ed22b401125c9eebff3171f570258854dbce3ecd55475"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a50431bf02583e21bf273c71b89d710e7a710ad5e39c725b14e685610555926f"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78af06ddc7fe5cc0e967085a9115accee665fb912c22a3f54bad70cc65b05fe6"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70d0738ef8fee13c003b100c2fbd667ec4f133468109b3472d249231108283a3"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2f6fd8a1cea5bbe599b6e78a6e5ee08db434fc8ffea51ff201c8765679698b3"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8177002868d1426305bb5de1e138161c2ec9eb2d939be38291d7c431c4712df8"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:008b839781d6c9bf3b6a8984d1d8e56f0ec46dc56df61fd669c49b58ae800400"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:a55b9132bb1ade6c734ddd2759c8dc132aa63687d259e725221f106b83a0e485"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a46fdec0083a26415f11d5f236b79fa1291c32aaa4a17684d82f7017a1f818b1"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8a63b640a7845f2bdd232eb0d0a4a2dd939bcdd6c57e6bb134526487f3160ec5"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7e32721e5d4922deaaf963469d795d5bde6093207c52fec719bd22e5d1bedbc4"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2c426b99a068601b5f4623573df7a7c3d72e87533a2dd2253353a03e7502566c"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4fc9b7fe29478824361ead6e14e4f5aed570d477e06088826537e202d25fe859"},
+ {file = "rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8"},
+]
+
+[[package]]
+name = "rsa"
+version = "4.9.1"
+description = "Pure-Python RSA implementation"
+optional = false
+python-versions = "<4,>=3.6"
+groups = ["main"]
+files = [
+ {file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"},
+ {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"},
+]
+
+[package.dependencies]
+pyasn1 = ">=0.1.3"
+
+[[package]]
+name = "ruff"
+version = "0.12.12"
+description = "An extremely fast Python linter and code formatter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "ruff-0.12.12-py3-none-linux_armv6l.whl", hash = "sha256:de1c4b916d98ab289818e55ce481e2cacfaad7710b01d1f990c497edf217dafc"},
+ {file = "ruff-0.12.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7acd6045e87fac75a0b0cdedacf9ab3e1ad9d929d149785903cff9bb69ad9727"},
+ {file = "ruff-0.12.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:abf4073688d7d6da16611f2f126be86523a8ec4343d15d276c614bda8ec44edb"},
+ {file = "ruff-0.12.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:968e77094b1d7a576992ac078557d1439df678a34c6fe02fd979f973af167577"},
+ {file = "ruff-0.12.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42a67d16e5b1ffc6d21c5f67851e0e769517fb57a8ebad1d0781b30888aa704e"},
+ {file = "ruff-0.12.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b216ec0a0674e4b1214dcc998a5088e54eaf39417327b19ffefba1c4a1e4971e"},
+ {file = "ruff-0.12.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:59f909c0fdd8f1dcdbfed0b9569b8bf428cf144bec87d9de298dcd4723f5bee8"},
+ {file = "ruff-0.12.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ac93d87047e765336f0c18eacad51dad0c1c33c9df7484c40f98e1d773876f5"},
+ {file = "ruff-0.12.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01543c137fd3650d322922e8b14cc133b8ea734617c4891c5a9fccf4bfc9aa92"},
+ {file = "ruff-0.12.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afc2fa864197634e549d87fb1e7b6feb01df0a80fd510d6489e1ce8c0b1cc45"},
+ {file = "ruff-0.12.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0c0945246f5ad776cb8925e36af2438e66188d2b57d9cf2eed2c382c58b371e5"},
+ {file = "ruff-0.12.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a0fbafe8c58e37aae28b84a80ba1817f2ea552e9450156018a478bf1fa80f4e4"},
+ {file = "ruff-0.12.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b9c456fb2fc8e1282affa932c9e40f5ec31ec9cbb66751a316bd131273b57c23"},
+ {file = "ruff-0.12.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5f12856123b0ad0147d90b3961f5c90e7427f9acd4b40050705499c98983f489"},
+ {file = "ruff-0.12.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:26a1b5a2bf7dd2c47e3b46d077cd9c0fc3b93e6c6cc9ed750bd312ae9dc302ee"},
+ {file = "ruff-0.12.12-py3-none-win32.whl", hash = "sha256:173be2bfc142af07a01e3a759aba6f7791aa47acf3604f610b1c36db888df7b1"},
+ {file = "ruff-0.12.12-py3-none-win_amd64.whl", hash = "sha256:e99620bf01884e5f38611934c09dd194eb665b0109104acae3ba6102b600fd0d"},
+ {file = "ruff-0.12.12-py3-none-win_arm64.whl", hash = "sha256:2a8199cab4ce4d72d158319b63370abf60991495fb733db96cd923a34c52d093"},
+ {file = "ruff-0.12.12.tar.gz", hash = "sha256:b86cd3415dbe31b3b46a71c598f4c4b2f550346d1ccf6326b347cc0c8fd063d6"},
+]
+
+[[package]]
+name = "s3transfer"
+version = "0.13.1"
+description = "An Amazon S3 Transfer Manager"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "s3transfer-0.13.1-py3-none-any.whl", hash = "sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724"},
+ {file = "s3transfer-0.13.1.tar.gz", hash = "sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf"},
+]
+
+[package.dependencies]
+botocore = ">=1.37.4,<2.0a.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"]
+
+[[package]]
+name = "scikit-image"
+version = "0.25.2"
+description = "Image processing in Python"
+optional = false
+python-versions = ">=3.10"
+groups = ["main"]
+files = [
+ {file = "scikit_image-0.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d3278f586793176599df6a4cf48cb6beadae35c31e58dc01a98023af3dc31c78"},
+ {file = "scikit_image-0.25.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5c311069899ce757d7dbf1d03e32acb38bb06153236ae77fcd820fd62044c063"},
+ {file = "scikit_image-0.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be455aa7039a6afa54e84f9e38293733a2622b8c2fb3362b822d459cc5605e99"},
+ {file = "scikit_image-0.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4c464b90e978d137330be433df4e76d92ad3c5f46a22f159520ce0fdbea8a09"},
+ {file = "scikit_image-0.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:60516257c5a2d2f74387c502aa2f15a0ef3498fbeaa749f730ab18f0a40fd054"},
+ {file = "scikit_image-0.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f4bac9196fb80d37567316581c6060763b0f4893d3aca34a9ede3825bc035b17"},
+ {file = "scikit_image-0.25.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d989d64ff92e0c6c0f2018c7495a5b20e2451839299a018e0e5108b2680f71e0"},
+ {file = "scikit_image-0.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2cfc96b27afe9a05bc92f8c6235321d3a66499995675b27415e0d0c76625173"},
+ {file = "scikit_image-0.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24cc986e1f4187a12aa319f777b36008764e856e5013666a4a83f8df083c2641"},
+ {file = "scikit_image-0.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:b4f6b61fc2db6340696afe3db6b26e0356911529f5f6aee8c322aa5157490c9b"},
+ {file = "scikit_image-0.25.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8db8dd03663112783221bf01ccfc9512d1cc50ac9b5b0fe8f4023967564719fb"},
+ {file = "scikit_image-0.25.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:483bd8cc10c3d8a7a37fae36dfa5b21e239bd4ee121d91cad1f81bba10cfb0ed"},
+ {file = "scikit_image-0.25.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d1e80107bcf2bf1291acfc0bf0425dceb8890abe9f38d8e94e23497cbf7ee0d"},
+ {file = "scikit_image-0.25.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a17e17eb8562660cc0d31bb55643a4da996a81944b82c54805c91b3fe66f4824"},
+ {file = "scikit_image-0.25.2-cp312-cp312-win_amd64.whl", hash = "sha256:bdd2b8c1de0849964dbc54037f36b4e9420157e67e45a8709a80d727f52c7da2"},
+ {file = "scikit_image-0.25.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7efa888130f6c548ec0439b1a7ed7295bc10105458a421e9bf739b457730b6da"},
+ {file = "scikit_image-0.25.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:dd8011efe69c3641920614d550f5505f83658fe33581e49bed86feab43a180fc"},
+ {file = "scikit_image-0.25.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28182a9d3e2ce3c2e251383bdda68f8d88d9fff1a3ebe1eb61206595c9773341"},
+ {file = "scikit_image-0.25.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8abd3c805ce6944b941cfed0406d88faeb19bab3ed3d4b50187af55cf24d147"},
+ {file = "scikit_image-0.25.2-cp313-cp313-win_amd64.whl", hash = "sha256:64785a8acefee460ec49a354706db0b09d1f325674107d7fa3eadb663fb56d6f"},
+ {file = "scikit_image-0.25.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:330d061bd107d12f8d68f1d611ae27b3b813b8cdb0300a71d07b1379178dd4cd"},
+ {file = "scikit_image-0.25.2.tar.gz", hash = "sha256:e5a37e6cd4d0c018a7a55b9d601357e3382826d3888c10d0213fc63bff977dde"},
+]
+
+[package.dependencies]
+imageio = ">=2.33,<2.35.0 || >2.35.0"
+lazy-loader = ">=0.4"
+networkx = ">=3.0"
+numpy = ">=1.24"
+packaging = ">=21"
+pillow = ">=10.1"
+scipy = ">=1.11.4"
+tifffile = ">=2022.8.12"
+
+[package.extras]
+build = ["Cython (>=3.0.8)", "build (>=1.2.1)", "meson-python (>=0.16)", "ninja (>=1.11.1.1)", "numpy (>=2.0)", "pythran (>=0.16)", "spin (==0.13)"]
+data = ["pooch (>=1.6.0)"]
+developer = ["ipython", "pre-commit", "tomli ; python_version < \"3.11\""]
+docs = ["PyWavelets (>=1.6)", "dask[array] (>=2023.2.0)", "intersphinx-registry (>=0.2411.14)", "ipykernel", "ipywidgets", "kaleido (==0.2.1)", "matplotlib (>=3.7)", "myst-parser", "numpydoc (>=1.7)", "pandas (>=2.0)", "plotly (>=5.20)", "pooch (>=1.6)", "pydata-sphinx-theme (>=0.16)", "pytest-doctestplus", "scikit-learn (>=1.2)", "seaborn (>=0.11)", "sphinx (>=8.0)", "sphinx-copybutton", "sphinx-gallery[parallel] (>=0.18)", "sphinx_design (>=0.5)", "tifffile (>=2022.8.12)"]
+optional = ["PyWavelets (>=1.6)", "SimpleITK", "astropy (>=5.0)", "cloudpickle (>=1.1.1)", "dask[array] (>=2023.2.0)", "matplotlib (>=3.7)", "pooch (>=1.6.0)", "pyamg (>=5.2)", "scikit-learn (>=1.2)"]
+test = ["asv", "numpydoc (>=1.7)", "pooch (>=1.6.0)", "pytest (>=8)", "pytest-cov (>=2.11.0)", "pytest-doctestplus", "pytest-faulthandler", "pytest-localserver"]
+
+[[package]]
+name = "scipy"
+version = "1.15.2"
+description = "Fundamental algorithms for scientific computing in Python"
+optional = false
+python-versions = ">=3.10"
+groups = ["main"]
+files = [
+ {file = "scipy-1.15.2-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a2ec871edaa863e8213ea5df811cd600734f6400b4af272e1c011e69401218e9"},
+ {file = "scipy-1.15.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:6f223753c6ea76983af380787611ae1291e3ceb23917393079dcc746ba60cfb5"},
+ {file = "scipy-1.15.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:ecf797d2d798cf7c838c6d98321061eb3e72a74710e6c40540f0e8087e3b499e"},
+ {file = "scipy-1.15.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:9b18aa747da280664642997e65aab1dd19d0c3d17068a04b3fe34e2559196cb9"},
+ {file = "scipy-1.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87994da02e73549dfecaed9e09a4f9d58a045a053865679aeb8d6d43747d4df3"},
+ {file = "scipy-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69ea6e56d00977f355c0f84eba69877b6df084516c602d93a33812aa04d90a3d"},
+ {file = "scipy-1.15.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:888307125ea0c4466287191e5606a2c910963405ce9671448ff9c81c53f85f58"},
+ {file = "scipy-1.15.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9412f5e408b397ff5641080ed1e798623dbe1ec0d78e72c9eca8992976fa65aa"},
+ {file = "scipy-1.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:b5e025e903b4f166ea03b109bb241355b9c42c279ea694d8864d033727205e65"},
+ {file = "scipy-1.15.2-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:92233b2df6938147be6fa8824b8136f29a18f016ecde986666be5f4d686a91a4"},
+ {file = "scipy-1.15.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:62ca1ff3eb513e09ed17a5736929429189adf16d2d740f44e53270cc800ecff1"},
+ {file = "scipy-1.15.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4c6676490ad76d1c2894d77f976144b41bd1a4052107902238047fb6a473e971"},
+ {file = "scipy-1.15.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:a8bf5cb4a25046ac61d38f8d3c3426ec11ebc350246a4642f2f315fe95bda655"},
+ {file = "scipy-1.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a8e34cf4c188b6dd004654f88586d78f95639e48a25dfae9c5e34a6dc34547e"},
+ {file = "scipy-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28a0d2c2075946346e4408b211240764759e0fabaeb08d871639b5f3b1aca8a0"},
+ {file = "scipy-1.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:42dabaaa798e987c425ed76062794e93a243be8f0f20fff6e7a89f4d61cb3d40"},
+ {file = "scipy-1.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f5e296ec63c5da6ba6fa0343ea73fd51b8b3e1a300b0a8cae3ed4b1122c7462"},
+ {file = "scipy-1.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:597a0c7008b21c035831c39927406c6181bcf8f60a73f36219b69d010aa04737"},
+ {file = "scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c4697a10da8f8765bb7c83e24a470da5797e37041edfd77fd95ba3811a47c4fd"},
+ {file = "scipy-1.15.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:869269b767d5ee7ea6991ed7e22b3ca1f22de73ab9a49c44bad338b725603301"},
+ {file = "scipy-1.15.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bad78d580270a4d32470563ea86c6590b465cb98f83d760ff5b0990cb5518a93"},
+ {file = "scipy-1.15.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:b09ae80010f52efddb15551025f9016c910296cf70adbf03ce2a8704f3a5ad20"},
+ {file = "scipy-1.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a6fd6eac1ce74a9f77a7fc724080d507c5812d61e72bd5e4c489b042455865e"},
+ {file = "scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b871df1fe1a3ba85d90e22742b93584f8d2b8e6124f8372ab15c71b73e428b8"},
+ {file = "scipy-1.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:03205d57a28e18dfd39f0377d5002725bf1f19a46f444108c29bdb246b6c8a11"},
+ {file = "scipy-1.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:601881dfb761311045b03114c5fe718a12634e5608c3b403737ae463c9885d53"},
+ {file = "scipy-1.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:e7c68b6a43259ba0aab737237876e5c2c549a031ddb7abc28c7b47f22e202ded"},
+ {file = "scipy-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01edfac9f0798ad6b46d9c4c9ca0e0ad23dbf0b1eb70e96adb9fa7f525eff0bf"},
+ {file = "scipy-1.15.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:08b57a9336b8e79b305a143c3655cc5bdbe6d5ece3378578888d2afbb51c4e37"},
+ {file = "scipy-1.15.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:54c462098484e7466362a9f1672d20888f724911a74c22ae35b61f9c5919183d"},
+ {file = "scipy-1.15.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:cf72ff559a53a6a6d77bd8eefd12a17995ffa44ad86c77a5df96f533d4e6c6bb"},
+ {file = "scipy-1.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9de9d1416b3d9e7df9923ab23cd2fe714244af10b763975bea9e4f2e81cebd27"},
+ {file = "scipy-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb530e4794fc8ea76a4a21ccb67dea33e5e0e60f07fc38a49e821e1eae3b71a0"},
+ {file = "scipy-1.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5ea7ed46d437fc52350b028b1d44e002646e28f3e8ddc714011aaf87330f2f32"},
+ {file = "scipy-1.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11e7ad32cf184b74380f43d3c0a706f49358b904fa7d5345f16ddf993609184d"},
+ {file = "scipy-1.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f"},
+ {file = "scipy-1.15.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:447ce30cee6a9d5d1379087c9e474628dab3db4a67484be1b7dc3196bfb2fac9"},
+ {file = "scipy-1.15.2-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:c90ebe8aaa4397eaefa8455a8182b164a6cc1d59ad53f79943f266d99f68687f"},
+ {file = "scipy-1.15.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:def751dd08243934c884a3221156d63e15234a3155cf25978b0a668409d45eb6"},
+ {file = "scipy-1.15.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:302093e7dfb120e55515936cb55618ee0b895f8bcaf18ff81eca086c17bd80af"},
+ {file = "scipy-1.15.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cd5b77413e1855351cdde594eca99c1f4a588c2d63711388b6a1f1c01f62274"},
+ {file = "scipy-1.15.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d0194c37037707b2afa7a2f2a924cf7bac3dc292d51b6a925e5fcb89bc5c776"},
+ {file = "scipy-1.15.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bae43364d600fdc3ac327db99659dcb79e6e7ecd279a75fe1266669d9a652828"},
+ {file = "scipy-1.15.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f031846580d9acccd0044efd1a90e6f4df3a6e12b4b6bd694a7bc03a89892b28"},
+ {file = "scipy-1.15.2-cp313-cp313t-win_amd64.whl", hash = "sha256:fe8a9eb875d430d81755472c5ba75e84acc980e4a8f6204d402849234d3017db"},
+ {file = "scipy-1.15.2.tar.gz", hash = "sha256:cd58a314d92838f7e6f755c8a2167ead4f27e1fd5c1251fd54289569ef3495ec"},
+]
+
+[package.dependencies]
+numpy = ">=1.23.5,<2.5"
+
+[package.extras]
+dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"]
+doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.16.5)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"]
+test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
+
+[[package]]
+name = "sentry-sdk"
+version = "2.22.0"
+description = "Python client for Sentry (https://sentry.io)"
+optional = false
+python-versions = ">=3.6"
+groups = ["main"]
+files = [
+ {file = "sentry_sdk-2.22.0-py2.py3-none-any.whl", hash = "sha256:3d791d631a6c97aad4da7074081a57073126c69487560c6f8bffcf586461de66"},
+ {file = "sentry_sdk-2.22.0.tar.gz", hash = "sha256:b4bf43bb38f547c84b2eadcefbe389b36ef75f3f38253d7a74d6b928c07ae944"},
+]
+
+[package.dependencies]
+certifi = "*"
+urllib3 = ">=1.26.11"
+
+[package.extras]
+aiohttp = ["aiohttp (>=3.5)"]
+anthropic = ["anthropic (>=0.16)"]
+arq = ["arq (>=0.23)"]
+asyncpg = ["asyncpg (>=0.23)"]
+beam = ["apache-beam (>=2.12)"]
+bottle = ["bottle (>=0.12.13)"]
+celery = ["celery (>=3)"]
+celery-redbeat = ["celery-redbeat (>=2)"]
+chalice = ["chalice (>=1.16.0)"]
+clickhouse-driver = ["clickhouse-driver (>=0.2.0)"]
+django = ["django (>=1.8)"]
+falcon = ["falcon (>=1.4)"]
+fastapi = ["fastapi (>=0.79.0)"]
+flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"]
+grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"]
+http2 = ["httpcore[http2] (==1.*)"]
+httpx = ["httpx (>=0.16.0)"]
+huey = ["huey (>=2)"]
+huggingface-hub = ["huggingface_hub (>=0.22)"]
+langchain = ["langchain (>=0.0.210)"]
+launchdarkly = ["launchdarkly-server-sdk (>=9.8.0)"]
+litestar = ["litestar (>=2.0.0)"]
+loguru = ["loguru (>=0.5)"]
+openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"]
+openfeature = ["openfeature-sdk (>=0.7.1)"]
+opentelemetry = ["opentelemetry-distro (>=0.35b0)"]
+opentelemetry-experimental = ["opentelemetry-distro"]
+pure-eval = ["asttokens", "executing", "pure_eval"]
+pymongo = ["pymongo (>=3.1)"]
+pyspark = ["pyspark (>=2.4.4)"]
+quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
+rq = ["rq (>=0.6)"]
+sanic = ["sanic (>=0.8)"]
+sqlalchemy = ["sqlalchemy (>=1.2)"]
+starlette = ["starlette (>=0.19.1)"]
+starlite = ["starlite (>=1.48)"]
+statsig = ["statsig (>=0.55.3)"]
+tornado = ["tornado (>=6)"]
+unleash = ["UnleashClient (>=6.0.1)"]
+
+[[package]]
+name = "setuptools"
+version = "80.1.0"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.9"
+groups = ["main", "dev"]
+files = [
+ {file = "setuptools-80.1.0-py3-none-any.whl", hash = "sha256:ea0e7655c05b74819f82e76e11a85b31779fee7c4969e82f72bab0664e8317e4"},
+ {file = "setuptools-80.1.0.tar.gz", hash = "sha256:2e308396e1d83de287ada2c2fd6e64286008fe6aca5008e0b6a8cb0e2c86eedd"},
+]
+
+[package.extras]
+check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""]
+core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"]
+cover = ["pytest-cov"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
+enabler = ["pytest-enabler (>=2.2)"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
+type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+groups = ["main"]
+files = [
+ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
+ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
+]
+
+[[package]]
+name = "sniffio"
+version = "1.3.1"
+description = "Sniff out which async library your code is running under"
+optional = false
+python-versions = ">=3.7"
+groups = ["docs"]
+files = [
+ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
+ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
+]
+
+[[package]]
+name = "snowballstemmer"
+version = "3.0.1"
+description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*"
+groups = ["docs"]
+files = [
+ {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"},
+ {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"},
+]
+
+[[package]]
+name = "soupsieve"
+version = "2.8"
+description = "A modern CSS selector implementation for Beautiful Soup."
+optional = false
+python-versions = ">=3.9"
+groups = ["main", "dev"]
+files = [
+ {file = "soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c"},
+ {file = "soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f"},
+]
+
+[[package]]
+name = "sphinx"
+version = "8.2.3"
+description = "Python documentation generator"
+optional = false
+python-versions = ">=3.11"
+groups = ["docs"]
+files = [
+ {file = "sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3"},
+ {file = "sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348"},
+]
+
+[package.dependencies]
+alabaster = ">=0.7.14"
+babel = ">=2.13"
+colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""}
+docutils = ">=0.20,<0.22"
+imagesize = ">=1.3"
+Jinja2 = ">=3.1"
+packaging = ">=23.0"
+Pygments = ">=2.17"
+requests = ">=2.30.0"
+roman-numerals-py = ">=1.0.0"
+snowballstemmer = ">=2.2"
+sphinxcontrib-applehelp = ">=1.0.7"
+sphinxcontrib-devhelp = ">=1.0.6"
+sphinxcontrib-htmlhelp = ">=2.0.6"
+sphinxcontrib-jsmath = ">=1.0.1"
+sphinxcontrib-qthelp = ">=1.0.6"
+sphinxcontrib-serializinghtml = ">=1.1.9"
+
+[package.extras]
+docs = ["sphinxcontrib-websupport"]
+lint = ["betterproto (==2.0.0b6)", "mypy (==1.15.0)", "pypi-attestations (==0.0.21)", "pyright (==1.1.395)", "pytest (>=8.0)", "ruff (==0.9.9)", "sphinx-lint (>=0.9)", "types-Pillow (==10.2.0.20240822)", "types-Pygments (==2.19.0.20250219)", "types-colorama (==0.4.15.20240311)", "types-defusedxml (==0.7.0.20240218)", "types-docutils (==0.21.0.20241128)", "types-requests (==2.32.0.20241016)", "types-urllib3 (==1.26.25.14)"]
+test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "pytest-xdist[psutil] (>=3.4)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"]
+
+[[package]]
+name = "sphinx-autobuild"
+version = "2024.10.3"
+description = "Rebuild Sphinx documentation on changes, with hot reloading in the browser."
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "sphinx_autobuild-2024.10.3-py3-none-any.whl", hash = "sha256:158e16c36f9d633e613c9aaf81c19b0fc458ca78b112533b20dafcda430d60fa"},
+ {file = "sphinx_autobuild-2024.10.3.tar.gz", hash = "sha256:248150f8f333e825107b6d4b86113ab28fa51750e5f9ae63b59dc339be951fb1"},
+]
+
+[package.dependencies]
+colorama = ">=0.4.6"
+sphinx = "*"
+starlette = ">=0.35"
+uvicorn = ">=0.25"
+watchfiles = ">=0.20"
+websockets = ">=11"
+
+[package.extras]
+test = ["httpx", "pytest (>=6)"]
+
+[[package]]
+name = "sphinx-rtd-theme"
+version = "3.0.2"
+description = "Read the Docs theme for Sphinx"
+optional = false
+python-versions = ">=3.8"
+groups = ["docs"]
+files = [
+ {file = "sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13"},
+ {file = "sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85"},
+]
+
+[package.dependencies]
+docutils = ">0.18,<0.22"
+sphinx = ">=6,<9"
+sphinxcontrib-jquery = ">=4,<5"
+
+[package.extras]
+dev = ["bump2version", "transifex-client", "twine", "wheel"]
+
+[[package]]
+name = "sphinxcontrib-applehelp"
+version = "2.0.0"
+description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"},
+ {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-devhelp"
+version = "2.0.0"
+description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents"
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"},
+ {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-htmlhelp"
+version = "2.1.0"
+description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"},
+ {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["html5lib", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-jquery"
+version = "4.1"
+description = "Extension to include jQuery on newer Sphinx releases"
+optional = false
+python-versions = ">=2.7"
+groups = ["docs"]
+files = [
+ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"},
+ {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"},
+]
+
+[package.dependencies]
+Sphinx = ">=1.8"
+
+[[package]]
+name = "sphinxcontrib-jsmath"
+version = "1.0.1"
+description = "A sphinx extension which renders display math in HTML via JavaScript"
+optional = false
+python-versions = ">=3.5"
+groups = ["docs"]
+files = [
+ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
+ {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
+]
+
+[package.extras]
+test = ["flake8", "mypy", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-qthelp"
+version = "2.0.0"
+description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents"
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"},
+ {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["defusedxml (>=0.7.1)", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-serializinghtml"
+version = "2.0.0"
+description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)"
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"},
+ {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["pytest"]
+
+[[package]]
+name = "starlette"
+version = "0.48.0"
+description = "The little ASGI library that shines."
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "starlette-0.48.0-py3-none-any.whl", hash = "sha256:0764ca97b097582558ecb498132ed0c7d942f233f365b86ba37770e026510659"},
+ {file = "starlette-0.48.0.tar.gz", hash = "sha256:7e8cee469a8ab2352911528110ce9088fdc6a37d9876926e73da7ce4aa4c7a46"},
+]
+
+[package.dependencies]
+anyio = ">=3.6.2,<5"
+
+[package.extras]
+full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
+
+[[package]]
+name = "stevedore"
+version = "5.4.1"
+description = "Manage dynamic plugins for Python applications"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "stevedore-5.4.1-py3-none-any.whl", hash = "sha256:d10a31c7b86cba16c1f6e8d15416955fc797052351a56af15e608ad20811fcfe"},
+ {file = "stevedore-5.4.1.tar.gz", hash = "sha256:3135b5ae50fe12816ef291baff420acb727fcd356106e3e9cbfa9e5985cd6f4b"},
+]
+
+[package.dependencies]
+pbr = ">=2.0.0"
+
+[[package]]
+name = "tifffile"
+version = "2025.10.4"
+description = "Read and write TIFF files"
+optional = false
+python-versions = ">=3.11"
+groups = ["main"]
+files = [
+ {file = "tifffile-2025.10.4-py3-none-any.whl", hash = "sha256:7687d691e49026053181470cec70fa9250e3a586b2041041297e38b10bbd34e1"},
+ {file = "tifffile-2025.10.4.tar.gz", hash = "sha256:2e437c16ab211be5bcdc79f71b4907359115f1f83b5d919e7c297c29725d3e38"},
+]
+
+[package.dependencies]
+numpy = "*"
+
+[package.extras]
+all = ["defusedxml", "fsspec", "imagecodecs (>=2024.12.30)", "kerchunk", "lxml", "matplotlib", "zarr (>=3.1.3)"]
+codecs = ["imagecodecs (>=2024.12.30)"]
+plot = ["matplotlib"]
+test = ["cmapfile", "czifile", "dask", "defusedxml", "fsspec", "imagecodecs", "kerchunk", "lfdfiles", "lxml", "ndtiff", "oiffile", "psdtags", "pytest", "requests", "roifile", "xarray", "zarr (>=3.1.3)"]
+xml = ["defusedxml", "lxml"]
+zarr = ["fsspec", "kerchunk", "zarr (>=3.1.3)"]
+
+[[package]]
+name = "tinycss2"
+version = "1.4.0"
+description = "A tiny CSS parser"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289"},
+ {file = "tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7"},
+]
+
+[package.dependencies]
+webencodings = ">=0.4"
+
+[package.extras]
+doc = ["sphinx", "sphinx_rtd_theme"]
+test = ["pytest", "ruff"]
+
+[[package]]
+name = "tornado"
+version = "6.5.1"
+description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "tornado-6.5.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d50065ba7fd11d3bd41bcad0825227cc9a95154bad83239357094c36708001f7"},
+ {file = "tornado-6.5.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9e9ca370f717997cb85606d074b0e5b247282cf5e2e1611568b8821afe0342d6"},
+ {file = "tornado-6.5.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b77e9dfa7ed69754a54c89d82ef746398be82f749df69c4d3abe75c4d1ff4888"},
+ {file = "tornado-6.5.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253b76040ee3bab8bcf7ba9feb136436a3787208717a1fb9f2c16b744fba7331"},
+ {file = "tornado-6.5.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:308473f4cc5a76227157cdf904de33ac268af770b2c5f05ca6c1161d82fdd95e"},
+ {file = "tornado-6.5.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:caec6314ce8a81cf69bd89909f4b633b9f523834dc1a352021775d45e51d9401"},
+ {file = "tornado-6.5.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:13ce6e3396c24e2808774741331638ee6c2f50b114b97a55c5b442df65fd9692"},
+ {file = "tornado-6.5.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5cae6145f4cdf5ab24744526cc0f55a17d76f02c98f4cff9daa08ae9a217448a"},
+ {file = "tornado-6.5.1-cp39-abi3-win32.whl", hash = "sha256:e0a36e1bc684dca10b1aa75a31df8bdfed656831489bc1e6a6ebed05dc1ec365"},
+ {file = "tornado-6.5.1-cp39-abi3-win_amd64.whl", hash = "sha256:908e7d64567cecd4c2b458075589a775063453aeb1d2a1853eedb806922f568b"},
+ {file = "tornado-6.5.1-cp39-abi3-win_arm64.whl", hash = "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7"},
+ {file = "tornado-6.5.1.tar.gz", hash = "sha256:84ceece391e8eb9b2b95578db65e920d2a61070260594819589609ba9bc6308c"},
+]
+
+[[package]]
+name = "traitlets"
+version = "5.14.3"
+description = "Traitlets Python configuration system"
+optional = false
+python-versions = ">=3.8"
+groups = ["main", "dev"]
+files = [
+ {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"},
+ {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"},
+]
+
+[package.extras]
+docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
+test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.15.0"
+description = "Backported and Experimental Type Hints for Python 3.9+"
+optional = false
+python-versions = ">=3.9"
+groups = ["main", "dev"]
+files = [
+ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"},
+ {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
+]
+
+[[package]]
+name = "tzdata"
+version = "2025.2"
+description = "Provider of IANA time zone data"
+optional = false
+python-versions = ">=2"
+groups = ["main"]
+files = [
+ {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"},
+ {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"},
+]
+
+[[package]]
+name = "unoserver"
+version = "3.3.2"
+description = "A server for file conversions with Libre Office"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "unoserver-3.3.2-py3-none-any.whl", hash = "sha256:87e144f903ee21951b2e06a97549450c13ed7eca5bcebad942d3352d4e882616"},
+ {file = "unoserver-3.3.2.tar.gz", hash = "sha256:1eeb7467cf6b56b8eff3b576e2d1b2b2ff4e0eb2052e995ac80a1456de300639"},
+]
+
+[package.extras]
+devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest", "pytest-cov", "zest.releaser"]
+
+[[package]]
+name = "urllib3"
+version = "2.5.0"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.9"
+groups = ["main", "dev", "docs"]
+files = [
+ {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"},
+ {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[[package]]
+name = "uvicorn"
+version = "0.37.0"
+description = "The lightning-fast ASGI server."
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "uvicorn-0.37.0-py3-none-any.whl", hash = "sha256:913b2b88672343739927ce381ff9e2ad62541f9f8289664fa1d1d3803fa2ce6c"},
+ {file = "uvicorn-0.37.0.tar.gz", hash = "sha256:4115c8add6d3fd536c8ee77f0e14a7fd2ebba939fed9b02583a97f80648f9e13"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+h11 = ">=0.8"
+
+[package.extras]
+standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"]
+
+[[package]]
+name = "vine"
+version = "5.1.0"
+description = "Python promises."
+optional = false
+python-versions = ">=3.6"
+groups = ["main"]
+files = [
+ {file = "vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc"},
+ {file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"},
+]
+
+[[package]]
+name = "watchfiles"
+version = "1.1.0"
+description = "Simple, modern and high performance file watching and code reload in python."
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "watchfiles-1.1.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:27f30e14aa1c1e91cb653f03a63445739919aef84c8d2517997a83155e7a2fcc"},
+ {file = "watchfiles-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3366f56c272232860ab45c77c3ca7b74ee819c8e1f6f35a7125556b198bbc6df"},
+ {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8412eacef34cae2836d891836a7fff7b754d6bcac61f6c12ba5ca9bc7e427b68"},
+ {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df670918eb7dd719642e05979fc84704af913d563fd17ed636f7c4783003fdcc"},
+ {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7642b9bc4827b5518ebdb3b82698ada8c14c7661ddec5fe719f3e56ccd13c97"},
+ {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:199207b2d3eeaeb80ef4411875a6243d9ad8bc35b07fc42daa6b801cc39cc41c"},
+ {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a479466da6db5c1e8754caee6c262cd373e6e6c363172d74394f4bff3d84d7b5"},
+ {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:935f9edd022ec13e447e5723a7d14456c8af254544cefbc533f6dd276c9aa0d9"},
+ {file = "watchfiles-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8076a5769d6bdf5f673a19d51da05fc79e2bbf25e9fe755c47595785c06a8c72"},
+ {file = "watchfiles-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86b1e28d4c37e89220e924305cd9f82866bb0ace666943a6e4196c5df4d58dcc"},
+ {file = "watchfiles-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d1caf40c1c657b27858f9774d5c0e232089bca9cb8ee17ce7478c6e9264d2587"},
+ {file = "watchfiles-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:a89c75a5b9bc329131115a409d0acc16e8da8dfd5867ba59f1dd66ae7ea8fa82"},
+ {file = "watchfiles-1.1.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:c9649dfc57cc1f9835551deb17689e8d44666315f2e82d337b9f07bd76ae3aa2"},
+ {file = "watchfiles-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:406520216186b99374cdb58bc48e34bb74535adec160c8459894884c983a149c"},
+ {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb45350fd1dc75cd68d3d72c47f5b513cb0578da716df5fba02fff31c69d5f2d"},
+ {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11ee4444250fcbeb47459a877e5e80ed994ce8e8d20283857fc128be1715dac7"},
+ {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bda8136e6a80bdea23e5e74e09df0362744d24ffb8cd59c4a95a6ce3d142f79c"},
+ {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b915daeb2d8c1f5cee4b970f2e2c988ce6514aace3c9296e58dd64dc9aa5d575"},
+ {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed8fc66786de8d0376f9f913c09e963c66e90ced9aa11997f93bdb30f7c872a8"},
+ {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe4371595edf78c41ef8ac8df20df3943e13defd0efcb732b2e393b5a8a7a71f"},
+ {file = "watchfiles-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b7c5f6fe273291f4d414d55b2c80d33c457b8a42677ad14b4b47ff025d0893e4"},
+ {file = "watchfiles-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7738027989881e70e3723c75921f1efa45225084228788fc59ea8c6d732eb30d"},
+ {file = "watchfiles-1.1.0-cp311-cp311-win32.whl", hash = "sha256:622d6b2c06be19f6e89b1d951485a232e3b59618def88dbeda575ed8f0d8dbf2"},
+ {file = "watchfiles-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:48aa25e5992b61debc908a61ab4d3f216b64f44fdaa71eb082d8b2de846b7d12"},
+ {file = "watchfiles-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:00645eb79a3faa70d9cb15c8d4187bb72970b2470e938670240c7998dad9f13a"},
+ {file = "watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179"},
+ {file = "watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5"},
+ {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297"},
+ {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0"},
+ {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e"},
+ {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee"},
+ {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd"},
+ {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f"},
+ {file = "watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4"},
+ {file = "watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f"},
+ {file = "watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd"},
+ {file = "watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47"},
+ {file = "watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6"},
+ {file = "watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30"},
+ {file = "watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a"},
+ {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc"},
+ {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b"},
+ {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895"},
+ {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a"},
+ {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b"},
+ {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c"},
+ {file = "watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b"},
+ {file = "watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb"},
+ {file = "watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9"},
+ {file = "watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7"},
+ {file = "watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef"},
+ {file = "watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb"},
+ {file = "watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297"},
+ {file = "watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018"},
+ {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0"},
+ {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12"},
+ {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb"},
+ {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77"},
+ {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92"},
+ {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e"},
+ {file = "watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b"},
+ {file = "watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8"},
+ {file = "watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db"},
+ {file = "watchfiles-1.1.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:865c8e95713744cf5ae261f3067861e9da5f1370ba91fc536431e29b418676fa"},
+ {file = "watchfiles-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42f92befc848bb7a19658f21f3e7bae80d7d005d13891c62c2cd4d4d0abb3433"},
+ {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0cc8365ab29487eb4f9979fd41b22549853389e22d5de3f134a6796e1b05a4"},
+ {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90ebb429e933645f3da534c89b29b665e285048973b4d2b6946526888c3eb2c7"},
+ {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c588c45da9b08ab3da81d08d7987dae6d2a3badd63acdb3e206a42dbfa7cb76f"},
+ {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c55b0f9f68590115c25272b06e63f0824f03d4fc7d6deed43d8ad5660cabdbf"},
+ {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd17a1e489f02ce9117b0de3c0b1fab1c3e2eedc82311b299ee6b6faf6c23a29"},
+ {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da71945c9ace018d8634822f16cbc2a78323ef6c876b1d34bbf5d5222fd6a72e"},
+ {file = "watchfiles-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:51556d5004887045dba3acdd1fdf61dddea2be0a7e18048b5e853dcd37149b86"},
+ {file = "watchfiles-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04e4ed5d1cd3eae68c89bcc1a485a109f39f2fd8de05f705e98af6b5f1861f1f"},
+ {file = "watchfiles-1.1.0-cp39-cp39-win32.whl", hash = "sha256:c600e85f2ffd9f1035222b1a312aff85fd11ea39baff1d705b9b047aad2ce267"},
+ {file = "watchfiles-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:3aba215958d88182e8d2acba0fdaf687745180974946609119953c0e112397dc"},
+ {file = "watchfiles-1.1.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a6fd40bbb50d24976eb275ccb55cd1951dfb63dbc27cae3066a6ca5f4beabd5"},
+ {file = "watchfiles-1.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9f811079d2f9795b5d48b55a37aa7773680a5659afe34b54cc1d86590a51507d"},
+ {file = "watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2726d7bfd9f76158c84c10a409b77a320426540df8c35be172444394b17f7ea"},
+ {file = "watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df32d59cb9780f66d165a9a7a26f19df2c7d24e3bd58713108b41d0ff4f929c6"},
+ {file = "watchfiles-1.1.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0ece16b563b17ab26eaa2d52230c9a7ae46cf01759621f4fbbca280e438267b3"},
+ {file = "watchfiles-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:51b81e55d40c4b4aa8658427a3ee7ea847c591ae9e8b81ef94a90b668999353c"},
+ {file = "watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2bcdc54ea267fe72bfc7d83c041e4eb58d7d8dc6f578dfddb52f037ce62f432"},
+ {file = "watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:923fec6e5461c42bd7e3fd5ec37492c6f3468be0499bc0707b4bbbc16ac21792"},
+ {file = "watchfiles-1.1.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7b3443f4ec3ba5aa00b0e9fa90cf31d98321cbff8b925a7c7b84161619870bc9"},
+ {file = "watchfiles-1.1.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7049e52167fc75fc3cc418fc13d39a8e520cbb60ca08b47f6cedb85e181d2f2a"},
+ {file = "watchfiles-1.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54062ef956807ba806559b3c3d52105ae1827a0d4ab47b621b31132b6b7e2866"},
+ {file = "watchfiles-1.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a7bd57a1bb02f9d5c398c0c1675384e7ab1dd39da0ca50b7f09af45fa435277"},
+ {file = "watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575"},
+]
+
+[package.dependencies]
+anyio = ">=3.0.0"
+
+[[package]]
+name = "waterbutler"
+version = "25.2.0"
+description = "WaterButler Storage Server"
+optional = false
+python-versions = "^3.13"
+groups = ["main"]
+files = []
+develop = false
+
+[package.dependencies]
+aiobotocore = "^2.22.0"
+aiocontextvars = "0.2.2"
+aiohttp = "3.10.5"
+boto3 = "^1.37.0"
+celery = "5.5.0"
+celery-amqp-backend = "^1.2.0"
+certifi = "2025.1.31"
+cryptography = "44.0.2"
+furl = "2.0.0"
+google-auth = "2.38.0"
+humanfriendly = "10.0"
+invoke = "2.2.0"
+multidict = ">=6.0.0"
+newrelic = "10.8.1"
+oauthlib = "3.2.2"
+pyjwe = "1.0.0"
+pyjwt = "2.10.1"
+python-dateutil = "2.9.0"
+pytz = "2025.1"
+redis = "5.2.1"
+ruff = "^0.12.7"
+sentry-sdk = "2.22.0"
+setuptools = "^80.1.0"
+stevedore = "5.4.1"
+tornado = "6.5.1"
+xmltodict = "0.14.2"
+yarl = "1.17.0"
+
+[package.source]
+type = "git"
+url = "https://github.com/CenterForOpenScience/waterbutler.git"
+reference = "feature/slurp-small-gcloud"
+resolved_reference = "4f2e590c5386c17bfb8808690101086f69194be9"
+
+[[package]]
+name = "wcwidth"
+version = "0.2.14"
+description = "Measures the displayed width of unicode strings in a terminal"
+optional = false
+python-versions = ">=3.6"
+groups = ["main", "dev"]
+files = [
+ {file = "wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1"},
+ {file = "wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605"},
+]
+
+[[package]]
+name = "webencodings"
+version = "0.5.1"
+description = "Character encoding aliases for legacy web content"
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"},
+ {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"},
+]
+
+[[package]]
+name = "websockets"
+version = "15.0.1"
+description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
+optional = false
+python-versions = ">=3.9"
+groups = ["docs"]
+files = [
+ {file = "websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b"},
+ {file = "websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205"},
+ {file = "websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a"},
+ {file = "websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e"},
+ {file = "websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf"},
+ {file = "websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb"},
+ {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d"},
+ {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9"},
+ {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c"},
+ {file = "websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256"},
+ {file = "websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41"},
+ {file = "websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431"},
+ {file = "websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57"},
+ {file = "websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905"},
+ {file = "websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562"},
+ {file = "websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792"},
+ {file = "websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413"},
+ {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8"},
+ {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3"},
+ {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf"},
+ {file = "websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85"},
+ {file = "websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065"},
+ {file = "websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3"},
+ {file = "websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665"},
+ {file = "websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2"},
+ {file = "websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215"},
+ {file = "websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5"},
+ {file = "websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65"},
+ {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe"},
+ {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4"},
+ {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597"},
+ {file = "websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9"},
+ {file = "websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7"},
+ {file = "websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931"},
+ {file = "websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675"},
+ {file = "websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151"},
+ {file = "websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22"},
+ {file = "websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f"},
+ {file = "websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8"},
+ {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375"},
+ {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d"},
+ {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4"},
+ {file = "websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa"},
+ {file = "websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561"},
+ {file = "websockets-15.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5"},
+ {file = "websockets-15.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a"},
+ {file = "websockets-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b"},
+ {file = "websockets-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770"},
+ {file = "websockets-15.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb"},
+ {file = "websockets-15.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054"},
+ {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee"},
+ {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed"},
+ {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880"},
+ {file = "websockets-15.0.1-cp39-cp39-win32.whl", hash = "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411"},
+ {file = "websockets-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123"},
+ {file = "websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f"},
+ {file = "websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee"},
+]
+
+[[package]]
+name = "wrapt"
+version = "1.17.3"
+description = "Module for decorators, wrappers and monkey patching."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04"},
+ {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2"},
+ {file = "wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c"},
+ {file = "wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775"},
+ {file = "wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd"},
+ {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05"},
+ {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418"},
+ {file = "wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390"},
+ {file = "wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6"},
+ {file = "wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18"},
+ {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7"},
+ {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85"},
+ {file = "wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f"},
+ {file = "wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311"},
+ {file = "wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1"},
+ {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5"},
+ {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2"},
+ {file = "wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89"},
+ {file = "wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77"},
+ {file = "wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a"},
+ {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0"},
+ {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba"},
+ {file = "wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd"},
+ {file = "wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828"},
+ {file = "wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9"},
+ {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396"},
+ {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc"},
+ {file = "wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe"},
+ {file = "wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c"},
+ {file = "wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6"},
+ {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0"},
+ {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77"},
+ {file = "wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7"},
+ {file = "wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277"},
+ {file = "wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d"},
+ {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa"},
+ {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050"},
+ {file = "wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8"},
+ {file = "wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb"},
+ {file = "wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16"},
+ {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39"},
+ {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235"},
+ {file = "wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c"},
+ {file = "wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b"},
+ {file = "wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa"},
+ {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7"},
+ {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4"},
+ {file = "wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10"},
+ {file = "wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6"},
+ {file = "wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58"},
+ {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a"},
+ {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067"},
+ {file = "wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454"},
+ {file = "wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e"},
+ {file = "wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f"},
+ {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056"},
+ {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804"},
+ {file = "wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977"},
+ {file = "wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116"},
+ {file = "wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6"},
+ {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225"},
+ {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a"},
+ {file = "wrapt-1.17.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f"},
+ {file = "wrapt-1.17.3-cp38-cp38-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00"},
+ {file = "wrapt-1.17.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56"},
+ {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5"},
+ {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22"},
+ {file = "wrapt-1.17.3-cp38-cp38-win32.whl", hash = "sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c"},
+ {file = "wrapt-1.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2"},
+ {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc"},
+ {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9"},
+ {file = "wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d"},
+ {file = "wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a"},
+ {file = "wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139"},
+ {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df"},
+ {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b"},
+ {file = "wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81"},
+ {file = "wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f"},
+ {file = "wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f"},
+ {file = "wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"},
+ {file = "wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"},
+]
+
+[[package]]
+name = "xlrd"
+version = "2.0.1"
+description = "Library for developers to extract data from Microsoft Excel (tm) .xls spreadsheet files"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+groups = ["main"]
+files = [
+ {file = "xlrd-2.0.1-py2.py3-none-any.whl", hash = "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd"},
+ {file = "xlrd-2.0.1.tar.gz", hash = "sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88"},
+]
+
+[package.extras]
+build = ["twine", "wheel"]
+docs = ["sphinx"]
+test = ["pytest", "pytest-cov"]
+
+[[package]]
+name = "xmltodict"
+version = "0.14.2"
+description = "Makes working with XML feel like you are working with JSON"
+optional = false
+python-versions = ">=3.6"
+groups = ["main"]
+files = [
+ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"},
+ {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"},
+]
+
+[[package]]
+name = "yarl"
+version = "1.17.0"
+description = "Yet another URL library"
+optional = false
+python-versions = ">=3.9"
+groups = ["main"]
+files = [
+ {file = "yarl-1.17.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2d8715edfe12eee6f27f32a3655f38d6c7410deb482158c0b7d4b7fad5d07628"},
+ {file = "yarl-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1803bf2a7a782e02db746d8bd18f2384801bc1d108723840b25e065b116ad726"},
+ {file = "yarl-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e66589110e20c2951221a938fa200c7aa134a8bdf4e4dc97e6b21539ff026d4"},
+ {file = "yarl-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7069d411cfccf868e812497e0ec4acb7c7bf8d684e93caa6c872f1e6f5d1664d"},
+ {file = "yarl-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cbf70ba16118db3e4b0da69dcde9d4d4095d383c32a15530564c283fa38a7c52"},
+ {file = "yarl-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0bc53cc349675b32ead83339a8de79eaf13b88f2669c09d4962322bb0f064cbc"},
+ {file = "yarl-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6aa18a402d1c80193ce97c8729871f17fd3e822037fbd7d9b719864018df746"},
+ {file = "yarl-1.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d89c5bc701861cfab357aa0cd039bc905fe919997b8c312b4b0c358619c38d4d"},
+ {file = "yarl-1.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b728bdf38ca58f2da1d583e4af4ba7d4cd1a58b31a363a3137a8159395e7ecc7"},
+ {file = "yarl-1.17.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:5542e57dc15d5473da5a39fbde14684b0cc4301412ee53cbab677925e8497c11"},
+ {file = "yarl-1.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e564b57e5009fb150cb513804d7e9e9912fee2e48835638f4f47977f88b4a39c"},
+ {file = "yarl-1.17.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:eb3c4cff524b4c1c1dba3a6da905edb1dfd2baf6f55f18a58914bbb2d26b59e1"},
+ {file = "yarl-1.17.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:05e13f389038842da930d439fbed63bdce3f7644902714cb68cf527c971af804"},
+ {file = "yarl-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:153c38ee2b4abba136385af4467459c62d50f2a3f4bde38c7b99d43a20c143ef"},
+ {file = "yarl-1.17.0-cp310-cp310-win32.whl", hash = "sha256:4065b4259d1ae6f70fd9708ffd61e1c9c27516f5b4fae273c41028afcbe3a094"},
+ {file = "yarl-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:abf366391a02a8335c5c26163b5fe6f514cc1d79e74d8bf3ffab13572282368e"},
+ {file = "yarl-1.17.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:19a4fe0279626c6295c5b0c8c2bb7228319d2e985883621a6e87b344062d8135"},
+ {file = "yarl-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cadd0113f4db3c6b56868d6a19ca6286f5ccfa7bc08c27982cf92e5ed31b489a"},
+ {file = "yarl-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:60d6693eef43215b1ccfb1df3f6eae8db30a9ff1e7989fb6b2a6f0b468930ee8"},
+ {file = "yarl-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb8bf3843e1fa8cf3fe77813c512818e57368afab7ebe9ef02446fe1a10b492"},
+ {file = "yarl-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2a5b35fd1d8d90443e061d0c8669ac7600eec5c14c4a51f619e9e105b136715"},
+ {file = "yarl-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c5bf17b32f392df20ab5c3a69d37b26d10efaa018b4f4e5643c7520d8eee7ac7"},
+ {file = "yarl-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48f51b529b958cd06e78158ff297a8bf57b4021243c179ee03695b5dbf9cb6e1"},
+ {file = "yarl-1.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fcaa06bf788e19f913d315d9c99a69e196a40277dc2c23741a1d08c93f4d430"},
+ {file = "yarl-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:32f3ee19ff0f18a7a522d44e869e1ebc8218ad3ae4ebb7020445f59b4bbe5897"},
+ {file = "yarl-1.17.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a4fb69a81ae2ec2b609574ae35420cf5647d227e4d0475c16aa861dd24e840b0"},
+ {file = "yarl-1.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7bacc8b77670322132a1b2522c50a1f62991e2f95591977455fd9a398b4e678d"},
+ {file = "yarl-1.17.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:437bf6eb47a2d20baaf7f6739895cb049e56896a5ffdea61a4b25da781966e8b"},
+ {file = "yarl-1.17.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:30534a03c87484092080e3b6e789140bd277e40f453358900ad1f0f2e61fc8ec"},
+ {file = "yarl-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b30df4ff98703649915144be6f0df3b16fd4870ac38a09c56d5d9e54ff2d5f96"},
+ {file = "yarl-1.17.0-cp311-cp311-win32.whl", hash = "sha256:263b487246858e874ab53e148e2a9a0de8465341b607678106829a81d81418c6"},
+ {file = "yarl-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:07055a9e8b647a362e7d4810fe99d8f98421575e7d2eede32e008c89a65a17bd"},
+ {file = "yarl-1.17.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:84095ab25ba69a8fa3fb4936e14df631b8a71193fe18bd38be7ecbe34d0f5512"},
+ {file = "yarl-1.17.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02608fb3f6df87039212fc746017455ccc2a5fc96555ee247c45d1e9f21f1d7b"},
+ {file = "yarl-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13468d291fe8c12162b7cf2cdb406fe85881c53c9e03053ecb8c5d3523822cd9"},
+ {file = "yarl-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8da3f8f368fb7e2f052fded06d5672260c50b5472c956a5f1bd7bf474ae504ab"},
+ {file = "yarl-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec0507ab6523980bed050137007c76883d941b519aca0e26d4c1ec1f297dd646"},
+ {file = "yarl-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08fc76df7fd8360e9ff30e6ccc3ee85b8dbd6ed5d3a295e6ec62bcae7601b932"},
+ {file = "yarl-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d522f390686acb6bab2b917dd9ca06740c5080cd2eaa5aef8827b97e967319d"},
+ {file = "yarl-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:147c527a80bb45b3dcd6e63401af8ac574125d8d120e6afe9901049286ff64ef"},
+ {file = "yarl-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:24cf43bcd17a0a1f72284e47774f9c60e0bf0d2484d5851f4ddf24ded49f33c6"},
+ {file = "yarl-1.17.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c28a44b9e0fba49c3857360e7ad1473fc18bc7f6659ca08ed4f4f2b9a52c75fa"},
+ {file = "yarl-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:350cacb2d589bc07d230eb995d88fcc646caad50a71ed2d86df533a465a4e6e1"},
+ {file = "yarl-1.17.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:fd1ab1373274dea1c6448aee420d7b38af163b5c4732057cd7ee9f5454efc8b1"},
+ {file = "yarl-1.17.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4934e0f96dadc567edc76d9c08181633c89c908ab5a3b8f698560124167d9488"},
+ {file = "yarl-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8d0a278170d75c88e435a1ce76557af6758bfebc338435b2eba959df2552163e"},
+ {file = "yarl-1.17.0-cp312-cp312-win32.whl", hash = "sha256:61584f33196575a08785bb56db6b453682c88f009cd9c6f338a10f6737ce419f"},
+ {file = "yarl-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:9987a439ad33a7712bd5bbd073f09ad10d38640425fa498ecc99d8aa064f8fc4"},
+ {file = "yarl-1.17.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8deda7b8eb15a52db94c2014acdc7bdd14cb59ec4b82ac65d2ad16dc234a109e"},
+ {file = "yarl-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56294218b348dcbd3d7fce0ffd79dd0b6c356cb2a813a1181af730b7c40de9e7"},
+ {file = "yarl-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1fab91292f51c884b290ebec0b309a64a5318860ccda0c4940e740425a67b6b7"},
+ {file = "yarl-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cf93fa61ff4d9c7d40482ce1a2c9916ca435e34a1b8451e17f295781ccc034f"},
+ {file = "yarl-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:261be774a0d71908c8830c33bacc89eef15c198433a8cc73767c10eeeb35a7d0"},
+ {file = "yarl-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:deec9693b67f6af856a733b8a3e465553ef09e5e8ead792f52c25b699b8f9e6e"},
+ {file = "yarl-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c804b07622ba50a765ca7fb8145512836ab65956de01307541def869e4a456c9"},
+ {file = "yarl-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d013a7c9574e98c14831a8f22d27277688ec3b2741d0188ac01a910b009987a"},
+ {file = "yarl-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e2cfcba719bd494c7413dcf0caafb51772dec168c7c946e094f710d6aa70494e"},
+ {file = "yarl-1.17.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:c068aba9fc5b94dfae8ea1cedcbf3041cd4c64644021362ffb750f79837e881f"},
+ {file = "yarl-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3616df510ffac0df3c9fa851a40b76087c6c89cbcea2de33a835fc80f9faac24"},
+ {file = "yarl-1.17.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:755d6176b442fba9928a4df787591a6a3d62d4969f05c406cad83d296c5d4e05"},
+ {file = "yarl-1.17.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c18f6e708d1cf9ff5b1af026e697ac73bea9cb70ee26a2b045b112548579bed2"},
+ {file = "yarl-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5b937c216b6dee8b858c6afea958de03c5ff28406257d22b55c24962a2baf6fd"},
+ {file = "yarl-1.17.0-cp313-cp313-win32.whl", hash = "sha256:d0131b14cb545c1a7bd98f4565a3e9bdf25a1bd65c83fc156ee5d8a8499ec4a3"},
+ {file = "yarl-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:01c96efa4313c01329e88b7e9e9e1b2fc671580270ddefdd41129fa8d0db7696"},
+ {file = "yarl-1.17.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0d44f67e193f0a7acdf552ecb4d1956a3a276c68e7952471add9f93093d1c30d"},
+ {file = "yarl-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:16ea0aa5f890cdcb7ae700dffa0397ed6c280840f637cd07bffcbe4b8d68b985"},
+ {file = "yarl-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cf5469dc7dcfa65edf5cc3a6add9f84c5529c6b556729b098e81a09a92e60e51"},
+ {file = "yarl-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e662bf2f6e90b73cf2095f844e2bc1fda39826472a2aa1959258c3f2a8500a2f"},
+ {file = "yarl-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8260e88f1446904ba20b558fa8ce5d0ab9102747238e82343e46d056d7304d7e"},
+ {file = "yarl-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dc16477a4a2c71e64c5d3d15d7ae3d3a6bb1e8b955288a9f73c60d2a391282f"},
+ {file = "yarl-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46027e326cecd55e5950184ec9d86c803f4f6fe4ba6af9944a0e537d643cdbe0"},
+ {file = "yarl-1.17.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc95e46c92a2b6f22e70afe07e34dbc03a4acd07d820204a6938798b16f4014f"},
+ {file = "yarl-1.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:16ca76c7ac9515320cd09d6cc083d8d13d1803f6ebe212b06ea2505fd66ecff8"},
+ {file = "yarl-1.17.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:eb1a5b97388f2613f9305d78a3473cdf8d80c7034e554d8199d96dcf80c62ac4"},
+ {file = "yarl-1.17.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:41fd5498975418cdc34944060b8fbeec0d48b2741068077222564bea68daf5a6"},
+ {file = "yarl-1.17.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:146ca582ed04a5664ad04b0e0603934281eaab5c0115a5a46cce0b3c061a56a1"},
+ {file = "yarl-1.17.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:6abb8c06107dbec97481b2392dafc41aac091a5d162edf6ed7d624fe7da0587a"},
+ {file = "yarl-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4d14be4613dd4f96c25feb4bd8c0d8ce0f529ab0ae555a17df5789e69d8ec0c5"},
+ {file = "yarl-1.17.0-cp39-cp39-win32.whl", hash = "sha256:174d6a6cad1068f7850702aad0c7b1bca03bcac199ca6026f84531335dfc2646"},
+ {file = "yarl-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:6af417ca2c7349b101d3fd557ad96b4cd439fdb6ab0d288e3f64a068eea394d0"},
+ {file = "yarl-1.17.0-py3-none-any.whl", hash = "sha256:62dd42bb0e49423f4dd58836a04fcf09c80237836796025211bbe913f1524993"},
+ {file = "yarl-1.17.0.tar.gz", hash = "sha256:d3f13583f378930377e02002b4085a3d025b00402d5a80911726d43a67911cd9"},
+]
+
+[package.dependencies]
+idna = ">=2.0"
+multidict = ">=4.0"
+propcache = ">=0.2.0"
+
+[metadata]
+lock-version = "2.1"
+python-versions = "^3.13"
+content-hash = "2f421e10ba9bc1825b7642e284c05c86f91e8de8a1817ff2a5c85797b8971a14"
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 000000000..75a6d5ce2
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,897 @@
+[tool.poetry]
+name = "mfr"
+version = "25.0.0"
+description = "Modular File Renderer"
+authors = ["Center for Open Science "]
+readme = "README.md"
+# requires-python = ">=3.13,<3.14"
+license = "Apache License 2.0"
+
+[tool.poetry.dependencies]
+python = "^3.13"
+aiohttp = "3.10.5"
+chardet = "5.2.0"
+furl = "2.0.0"
+humanfriendly = "10.0"
+invoke = "2.2.0"
+mako = "1.3.2"
+sentry-sdk = "2.22.0"
+setuptools = "80.1.0"
+stevedore = "5.4.1"
+tornado = "6.5.1"
+agent = "0.1.2"
+google-auth = "2.38.0"
+Pygments = "2.19.1"
+olefile = "0.47"
+Pillow = "11.2.1"
+psd-tools = "1.10.7"
+ipython = "7.31.1"
+nbconvert = "7.16.6"
+nbformat = "5.10.4"
+traitlets = "5.14.3"
+jsonschema = "4.24.0"
+jinja2 = "3.1.5"
+mistune = "3.1.2"
+reportlab = "4.4.0"
+docutils = "0.21.2"
+pandas = "2.2.3"
+xlrd = "2.0.1"
+h5py = "3.13"
+scipy = "1.15.2"
+markdown = "3.8.0"
+certifi = "2025.1.31"
+unoserver = "3.3.2"
+openpyxl = "^3.1"
+
+waterbutler = { git = "https://github.com/CenterForOpenScience/waterbutler.git", branch = "feature/slurp-small-gcloud" }
+markupsafe = "2.0.1"
+celery = "5.5.0"
+black = "^25.1.0"
+isort = "^6.0.1"
+ruff = "^0.12.7"
+
+
+[tool.poetry.group.dev]
+optional = true
+
+[tool.poetry.group.dev.dependencies]
+beautifulsoup4 = "4.13.3"
+colorlog = "6.9.0"
+coveralls = "3.3.1"
+flake8 = "7.1.2"
+ipdb = "0.13.13"
+mccabe = "0.7.0"
+pydevd = "3.3.0"
+pyflakes = "3.2.0"
+pytest = "8.1.1"
+pytest-cov = "4.1.0"
+pyzmq = "26.2.1"
+
+[tool.poetry.group.docs]
+optional = true
+
+[tool.poetry.group.docs.dependencies]
+sphinx = "8.2.3"
+sphinx-autobuild = "2024.10.3"
+sphinx-rtd-theme = "3.0.2"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.poetry.plugins."mfr.providers"]
+http = "mfr.providers.http:HttpProvider"
+osf = "mfr.providers.osf:OsfProvider"
+
+[tool.poetry.plugins."mfr.exporters"]
+
+gdraw = "mfr.extensions.image:ImageExporter"
+gdoc = "mfr.extensions.unoconv:UnoconvExporter"
+gsheet = "mfr.extensions.unoconv:UnoconvExporter"
+gslides = "mfr.extensions.unoconv:UnoconvExporter"
+
+# image
+jpg = "mfr.extensions.image:ImageExporter"
+jpeg = "mfr.extensions.image:ImageExporter"
+png = "mfr.extensions.image:ImageExporter"
+bmp = "mfr.extensions.image:ImageExporter"
+gif = "mfr.extensions.image:ImageExporter"
+psd = "mfr.extensions.image:ImageExporter"
+tif = "mfr.extensions.pdf:PdfExporter"
+tiff = "mfr.extensions.pdf:PdfExporter"
+
+# jsc3d
+stp = "mfr.extensions.jsc3d:JSC3DExporter"
+step = "mfr.extensions.jsc3d:JSC3DExporter"
+
+# unoconv
+# .bib = mfr.extensions.unoconv:UnoconvExporter
+# .bmp = mfr.extensions.unoconv:UnoconvExporter
+# .csv = mfr.extensions.unoconv:UnoconvExporter
+dbf = "mfr.extensions.unoconv:UnoconvExporter"
+dif = "mfr.extensions.unoconv:UnoconvExporter"
+doc = "mfr.extensions.unoconv:UnoconvExporter"
+docx = "mfr.extensions.unoconv:UnoconvExporter"
+emf = "mfr.extensions.unoconv:UnoconvExporter"
+eps = "mfr.extensions.unoconv:UnoconvExporter"
+fodg = "mfr.extensions.unoconv:UnoconvExporter"
+fodp = "mfr.extensions.unoconv:UnoconvExporter"
+fods = "mfr.extensions.unoconv:UnoconvExporter"
+fodt = "mfr.extensions.unoconv:UnoconvExporter"
+# .gif = mfr.extensions.unoconv:UnoconvExporter
+# .html = mfr.extensions.unoconv:UnoconvExporter
+# .jpg = mfr.extensions.unoconv:UnoconvExporter
+# .ltx = mfr.extensions.unoconv:UnoconvExporter
+met = "mfr.extensions.unoconv:UnoconvExporter"
+odd = "mfr.extensions.unoconv:UnoconvExporter"
+odg = "mfr.extensions.unoconv:UnoconvExporter"
+odp = "mfr.extensions.unoconv:UnoconvExporter"
+ods = "mfr.extensions.unoconv:UnoconvExporter"
+odt = "mfr.extensions.unoconv:UnoconvExporter"
+otg = "mfr.extensions.unoconv:UnoconvExporter"
+otp = "mfr.extensions.unoconv:UnoconvExporter"
+ots = "mfr.extensions.unoconv:UnoconvExporter"
+ott = "mfr.extensions.unoconv:UnoconvExporter"
+pbm = "mfr.extensions.unoconv:UnoconvExporter"
+pct = "mfr.extensions.unoconv:UnoconvExporter"
+# .pdb = mfr.extensions.unoconv:UnoconvExporter
+# .pdf = mfr.extensions.unoconv:UnoconvExporter
+pgm = "mfr.extensions.unoconv:UnoconvExporter"
+# .png = mfr.extensions.unoconv:UnoconvExporter
+pot = "mfr.extensions.unoconv:UnoconvExporter"
+potm = "mfr.extensions.unoconv:UnoconvExporter"
+ppm = "mfr.extensions.unoconv:UnoconvExporter"
+pps = "mfr.extensions.unoconv:UnoconvExporter"
+ppt = "mfr.extensions.unoconv:UnoconvExporter"
+pptx = "mfr.extensions.unoconv:UnoconvExporter"
+psw = "mfr.extensions.unoconv:UnoconvExporter"
+pwp = "mfr.extensions.unoconv:UnoconvExporter"
+pxl = "mfr.extensions.unoconv:UnoconvExporter"
+ras = "mfr.extensions.unoconv:UnoconvExporter"
+rtf = "mfr.extensions.unoconv:UnoconvExporter"
+sda = "mfr.extensions.unoconv:UnoconvExporter"
+sdc = "mfr.extensions.unoconv:UnoconvExporter"
+sdd = "mfr.extensions.unoconv:UnoconvExporter"
+sdw = "mfr.extensions.unoconv:UnoconvExporter"
+slk = "mfr.extensions.unoconv:UnoconvExporter"
+stc = "mfr.extensions.unoconv:UnoconvExporter"
+std = "mfr.extensions.unoconv:UnoconvExporter"
+sti = "mfr.extensions.unoconv:UnoconvExporter"
+stw = "mfr.extensions.unoconv:UnoconvExporter"
+svg = "mfr.extensions.unoconv:UnoconvExporter"
+svm = "mfr.extensions.unoconv:UnoconvExporter"
+# Renders junk at the moment
+# .swf = mfr.extensions.unoconv:UnoconvExporter
+sxc = "mfr.extensions.unoconv:UnoconvExporter"
+sxd = "mfr.extensions.unoconv:UnoconvExporter"
+sxi = "mfr.extensions.unoconv:UnoconvExporter"
+sxw = "mfr.extensions.unoconv:UnoconvExporter"
+# .tiff = "mfr.extensions.unoconv:UnoconvExporter"
+# .txt = mfr.extensions.unoconv:UnoconvExporter
+uop = "mfr.extensions.unoconv:UnoconvExporter"
+uos = "mfr.extensions.unoconv:UnoconvExporter"
+uot = "mfr.extensions.unoconv:UnoconvExporter"
+vor = "mfr.extensions.unoconv:UnoconvExporter"
+wmf = "mfr.extensions.unoconv:UnoconvExporter"
+wps = "mfr.extensions.unoconv:UnoconvExporter"
+# .xhtml = "mfr.extensions.unoconv:UnoconvExporter"
+# .xls = "mfr.extensions.unoconv:UnoconvExporter"
+# .xlsx = "mfr.extensions.unoconv:UnoconvExporter"
+xlt = "mfr.extensions.unoconv:UnoconvExporter"
+# .xml = "mfr.extensions.unoconv:UnoconvExporter"
+xpm = "mfr.extensions.unoconv:UnoconvExporter"
+
+[tool.poetry.plugins."mfr.renderers"]
+# audio
+mp3 = "mfr.extensions.audio:AudioRenderer"
+ogg = "mfr.extensions.audio:AudioRenderer"
+wav = "mfr.extensions.audio:AudioRenderer"
+
+# code pygments
+none = "mfr.extensions.codepygments:CodePygmentsRenderer"
+1 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+2 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+3 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+4 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+5 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+6 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+6pm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+6pl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+7 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+abap = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ada = "mfr.extensions.codepygments:CodePygmentsRenderer"
+adb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ads = "mfr.extensions.codepygments:CodePygmentsRenderer"
+agda = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ahk = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ahkl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+aj = "mfr.extensions.codepygments:CodePygmentsRenderer"
+als = "mfr.extensions.codepygments:CodePygmentsRenderer"
+amw = "mfr.extensions.codepygments:CodePygmentsRenderer"
+anl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+apl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+applescript = "mfr.extensions.codepygments:CodePygmentsRenderer"
+arexx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+as = "mfr.extensions.codepygments:CodePygmentsRenderer"
+asax = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ascx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ashx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+asm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+asmx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+aspx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+asy = "mfr.extensions.codepygments:CodePygmentsRenderer"
+at = "mfr.extensions.codepygments:CodePygmentsRenderer"
+au3 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+aux = "mfr.extensions.codepygments:CodePygmentsRenderer"
+awk = "mfr.extensions.codepygments:CodePygmentsRenderer"
+axd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+b = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bas = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bash = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bat = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bed = "mfr.extensions.codepygments:CodePygmentsRenderer"
+befunge = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bib = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bmx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+boa = "mfr.extensions.codepygments:CodePygmentsRenderer"
+boo = "mfr.extensions.codepygments:CodePygmentsRenderer"
+boxs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bro = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bst = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bug = "mfr.extensions.codepygments:CodePygmentsRenderer"
+c = "mfr.extensions.codepygments:CodePygmentsRenderer"
+c-objdump = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cbl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cdf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cmdi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ceylon = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cfc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cfg = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cfm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cfml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+chai = "mfr.extensions.codepygments:CodePygmentsRenderer"
+chpl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cirru = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+clay = "mfr.extensions.codepygments:CodePygmentsRenderer"
+clj = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cljs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cls = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cmake = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cmd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cob = "mfr.extensions.codepygments:CodePygmentsRenderer"
+coffee = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cpp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cpp-objdump = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cpy = "mfr.extensions.codepygments:CodePygmentsRenderer"
+croc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cry = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+csh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+csl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+css = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cu = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cuh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cw = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cxx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cxx-objdump = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cyp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+cypher = "mfr.extensions.codepygments:CodePygmentsRenderer"
+d = "mfr.extensions.codepygments:CodePygmentsRenderer"
+d-objdump = "mfr.extensions.codepygments:CodePygmentsRenderer"
+darcspatch = "mfr.extensions.codepygments:CodePygmentsRenderer"
+dart = "mfr.extensions.codepygments:CodePygmentsRenderer"
+decls = "mfr.extensions.codepygments:CodePygmentsRenderer"
+def = "mfr.extensions.codepygments:CodePygmentsRenderer"
+dg = "mfr.extensions.codepygments:CodePygmentsRenderer"
+di = "mfr.extensions.codepygments:CodePygmentsRenderer"
+diff = "mfr.extensions.codepygments:CodePygmentsRenderer"
+docker = "mfr.extensions.codepygments:CodePygmentsRenderer"
+dpatch = "mfr.extensions.codepygments:CodePygmentsRenderer"
+dtd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+duby = "mfr.extensions.codepygments:CodePygmentsRenderer"
+duel = "mfr.extensions.codepygments:CodePygmentsRenderer"
+dyl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+dylan = "mfr.extensions.codepygments:CodePygmentsRenderer"
+dylan-console = "mfr.extensions.codepygments:CodePygmentsRenderer"
+e = "mfr.extensions.codepygments:CodePygmentsRenderer"
+eaf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ebnf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ebuild = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ec = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ecl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+eclass = "mfr.extensions.codepygments:CodePygmentsRenderer"
+eh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+el = "mfr.extensions.codepygments:CodePygmentsRenderer"
+# .eps = "mfr.extensions.codepygments:CodePygmentsRenderer"
+eqn = "mfr.extensions.codepygments:CodePygmentsRenderer"
+erl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+erl-sh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+es = "mfr.extensions.codepygments:CodePygmentsRenderer"
+escript = "mfr.extensions.codepygments:CodePygmentsRenderer"
+evoque = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ex = "mfr.extensions.codepygments:CodePygmentsRenderer"
+exs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+f = "mfr.extensions.codepygments:CodePygmentsRenderer"
+f90 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+factor = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fan = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fancypack = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fas = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fasta = "mfr.extensions.codepygments:CodePygmentsRenderer"
+feature = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fhtml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+flx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+flxh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+frag = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fsi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fun = "mfr.extensions.codepygments:CodePygmentsRenderer"
+fy = "mfr.extensions.codepygments:CodePygmentsRenderer"
+g = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gap = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gdc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gdt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gemspec = "mfr.extensions.codepygments:CodePygmentsRenderer"
+geo = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+go = "mfr.extensions.codepygments:CodePygmentsRenderer"
+golo = "mfr.extensions.codepygments:CodePygmentsRenderer"
+groovy = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gsp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gst = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gsx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+h = "mfr.extensions.codepygments:CodePygmentsRenderer"
+haml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+handlebars = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hbs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hdp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hpp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hrl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+htm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+html = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hxml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hxsl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hxx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hy = "mfr.extensions.codepygments:CodePygmentsRenderer"
+hyb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+i = "mfr.extensions.codepygments:CodePygmentsRenderer"
+i6t = "mfr.extensions.codepygments:CodePygmentsRenderer"
+i7x = "mfr.extensions.codepygments:CodePygmentsRenderer"
+idc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+idr = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ijm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ik = "mfr.extensions.codepygments:CodePygmentsRenderer"
+inc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+inf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ini = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ino = "mfr.extensions.codepygments:CodePygmentsRenderer"
+inp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+intr = "mfr.extensions.codepygments:CodePygmentsRenderer"
+io = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ipf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+iqx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+j = "mfr.extensions.codepygments:CodePygmentsRenderer"
+jade = "mfr.extensions.codepygments:CodePygmentsRenderer"
+jag = "mfr.extensions.codepygments:CodePygmentsRenderer"
+java = "mfr.extensions.codepygments:CodePygmentsRenderer"
+jbst = "mfr.extensions.codepygments:CodePygmentsRenderer"
+jl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+js = "mfr.extensions.codepygments:CodePygmentsRenderer"
+json = "mfr.extensions.codepygments:CodePygmentsRenderer"
+jsonld = "mfr.extensions.codepygments:CodePygmentsRenderer"
+jsp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+jst = "mfr.extensions.codepygments:CodePygmentsRenderer"
+jsx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+kal = "mfr.extensions.codepygments:CodePygmentsRenderer"
+kid = "mfr.extensions.codepygments:CodePygmentsRenderer"
+kk = "mfr.extensions.codepygments:CodePygmentsRenderer"
+kki = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ksh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+kt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lagda = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lasso = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lcry = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lean = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lgs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lgt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lhs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lid = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lidr = "mfr.extensions.codepygments:CodePygmentsRenderer"
+liquid = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lisp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+list = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ll = "mfr.extensions.codepygments:CodePygmentsRenderer"
+log = "mfr.extensions.codepygments:CodePygmentsRenderer"
+logtalk = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ls = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lsl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lsp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lss = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lst = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ltx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lua = "mfr.extensions.codepygments:CodePygmentsRenderer"
+lyx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+m = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ma = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mak = "mfr.extensions.codepygments:CodePygmentsRenderer"
+man = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mao = "mfr.extensions.codepygments:CodePygmentsRenderer"
+maql = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mask = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mdp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mhtml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mk = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mli = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mll = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mly = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mo = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mod = "mfr.extensions.codepygments:CodePygmentsRenderer"
+monkey = "mfr.extensions.codepygments:CodePygmentsRenderer"
+moo = "mfr.extensions.codepygments:CodePygmentsRenderer"
+moon = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mq4 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mq5 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mqh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+msc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mu = "mfr.extensions.codepygments:CodePygmentsRenderer"
+mxml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+myt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+n = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nbp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nex = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ni = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nim = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nimrod = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nit = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nix = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nlogo = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nqp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ns2 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nsh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+nsi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+objdump = "mfr.extensions.codepygments:CodePygmentsRenderer"
+objdump-intel = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ooc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+opa = "mfr.extensions.codepygments:CodePygmentsRenderer"
+opensesame = "mfr.extensions.codepygments:CodePygmentsRenderer"
+org = "mfr.extensions.codepygments:CodePygmentsRenderer"
+p = "mfr.extensions.codepygments:CodePygmentsRenderer"
+p6 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+p6l = "mfr.extensions.codepygments:CodePygmentsRenderer"
+p6m = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pan = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pas = "mfr.extensions.codepygments:CodePygmentsRenderer"
+patch = "mfr.extensions.codepygments:CodePygmentsRenderer"
+php = "mfr.extensions.codepygments:CodePygmentsRenderer"
+phtml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pig = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pike = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pl6 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+plot = "mfr.extensions.codepygments:CodePygmentsRenderer"
+plt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pm6 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pmod = "mfr.extensions.codepygments:CodePygmentsRenderer"
+po = "mfr.extensions.codepygments:CodePygmentsRenderer"
+# .pot = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pov = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+praat = "mfr.extensions.codepygments:CodePygmentsRenderer"
+prg = "mfr.extensions.codepygments:CodePygmentsRenderer"
+prj = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pro = "mfr.extensions.codepygments:CodePygmentsRenderer"
+prolog = "mfr.extensions.codepygments:CodePygmentsRenderer"
+properties = "mfr.extensions.codepygments:CodePygmentsRenderer"
+proto = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ps = "mfr.extensions.codepygments:CodePygmentsRenderer"
+psydat = "mfr.extensions.codepygments:CodePygmentsRenderer"
+psyexp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ps1 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+psm1 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pwn = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pxd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pxi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+py = "mfr.extensions.codepygments:CodePygmentsRenderer"
+py3tb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pypylog = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pytb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pyw = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pyx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+pzfx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+qml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+qsf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+r = "mfr.extensions.codepygments:CodePygmentsRenderer"
+r3 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rake = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rbw = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rbx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rdf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+reb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+red = "mfr.extensions.codepygments:CodePygmentsRenderer"
+reds = "mfr.extensions.codepygments:CodePygmentsRenderer"
+reg = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rest = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rex = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rexx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rhtml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ris = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rkt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rktd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rktl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rm5 = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rnw = "mfr.extensions.codepygments:CodePygmentsRenderer"
+robot = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rout = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rpf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rq = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rql = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rs = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rsl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rss = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rvt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rx = "mfr.extensions.codepygments:CodePygmentsRenderer"
+s = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sage = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sass = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+scad = "mfr.extensions.codepygments:CodePygmentsRenderer"
+scala = "mfr.extensions.codepygments:CodePygmentsRenderer"
+scaml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sce = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sci = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sch = "mfr.extensions.codepygments:CodePygmentsRenderer"
+scm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+scss = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sdf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sh-session = "mfr.extensions.codepygments:CodePygmentsRenderer"
+shell-session = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sig = "mfr.extensions.codepygments:CodePygmentsRenderer"
+slim = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sls = "mfr.extensions.codepygments:CodePygmentsRenderer"
+smali = "mfr.extensions.codepygments:CodePygmentsRenderer"
+smcl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+snobol = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sparql = "mfr.extensions.codepygments:CodePygmentsRenderer"
+spec = "mfr.extensions.codepygments:CodePygmentsRenderer"
+spt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sql = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sqlite3-console = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ss = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ssp = "mfr.extensions.codepygments:CodePygmentsRenderer"
+st = "mfr.extensions.codepygments:CodePygmentsRenderer"
+stan = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sty = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sv = "mfr.extensions.codepygments:CodePygmentsRenderer"
+svh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+swg = "mfr.extensions.codepygments:CodePygmentsRenderer"
+swift = "mfr.extensions.codepygments:CodePygmentsRenderer"
+t = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tab = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tac = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tcl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tcsh = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tea = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tem = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tex = "mfr.extensions.codepygments:CodePygmentsRenderer"
+textgrid = "mfr.extensions.codepygments:CodePygmentsRenderer"
+thy = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tmpl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+toc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+todotxt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tpl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tre = "mfr.extensions.codepygments:CodePygmentsRenderer"
+treetop = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ts = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tst = "mfr.extensions.codepygments:CodePygmentsRenderer"
+tt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+ttl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+twig = "mfr.extensions.codepygments:CodePygmentsRenderer"
+txt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rmd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+do = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sas = "mfr.extensions.codepygments:CodePygmentsRenderer"
+sps = "mfr.extensions.codepygments:CodePygmentsRenderer"
+u = "mfr.extensions.codepygments:CodePygmentsRenderer"
+umbrella = "mfr.extensions.codepygments:CodePygmentsRenderer"
+v = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vala = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vapi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vark = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vb = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vert = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vhd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vhdl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vim = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vmrk = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vtk = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vtt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+weechatlog = "mfr.extensions.codepygments:CodePygmentsRenderer"
+wlua = "mfr.extensions.codepygments:CodePygmentsRenderer"
+wndpos = "mfr.extensions.codepygments:CodePygmentsRenderer"
+wsdl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+wsf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+x = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xhtml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xmi = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xpl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xq = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xql = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xqm = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xquery = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xqy = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xsd = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xsl = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xslt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xtend = "mfr.extensions.codepygments:CodePygmentsRenderer"
+xul = "mfr.extensions.codepygments:CodePygmentsRenderer"
+yaml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+yml = "mfr.extensions.codepygments:CodePygmentsRenderer"
+zep = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.*config.in* = "mfr.extensions.codepygments:CodePygmentsRenderer"
+renviron = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rhistory = "mfr.extensions.codepygments:CodePygmentsRenderer"
+rprofile = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.bash_* = "mfr.extensions.codepygments:CodePygmentsRenderer"
+bashrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+exrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+gvimrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+htaccess = "mfr.extensions.codepygments:CodePygmentsRenderer"
+vimrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.cmakelists.txt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.dockerfile = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.gnumakefile = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.kconfig = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.makefile = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.makefile.* = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.pkgbuild = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.rakefile = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.sconscript = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.sconstruct = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#._exrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#._gvimrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#._vimrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.apache.conf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.apache2.conf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.autodelegate = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.autohandler = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.bash_* = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.bashrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.control = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.dhandler = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.external.in* = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.gvimrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.makefile = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.sources.list = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.squid.conf = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.standard-modules.in = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.todo.txt = "mfr.extensions.codepygments:CodePygmentsRenderer"
+#.vimrc = "mfr.extensions.codepygments:CodePygmentsRenderer"
+
+# docx
+# .docx = mfr.extensions.docx:DocxRenderer
+
+# google docs
+gdraw = "mfr.extensions.image:ImageRenderer"
+gdoc = "mfr.extensions.unoconv:UnoconvRenderer"
+gsheet = "mfr.extensions.tabular:TabularRenderer"
+gslides = "mfr.extensions.unoconv:UnoconvRenderer"
+
+# image
+bmp = "mfr.extensions.image:ImageRenderer"
+jpg = "mfr.extensions.image:ImageRenderer"
+jpeg = "mfr.extensions.image:ImageRenderer"
+gif = "mfr.extensions.image:ImageRenderer"
+ico = "mfr.extensions.image:ImageRenderer"
+png = "mfr.extensions.image:ImageRenderer"
+psd = "mfr.extensions.image:ImageRenderer"
+tif = "mfr.extensions.pdf:PdfRenderer"
+tiff = "mfr.extensions.pdf:PdfRenderer"
+
+# ipynb
+ipynb = "mfr.extensions.ipynb:IpynbRenderer"
+
+# md
+md = "mfr.extensions.md:MdRenderer"
+markdown = "mfr.extensions.md:MdRenderer"
+
+# jsc3d
+3ds = "mfr.extensions.jsc3d:JSC3DRenderer"
+ctm = "mfr.extensions.jsc3d:JSC3DRenderer"
+obj = "mfr.extensions.jsc3d:JSC3DRenderer"
+stl = "mfr.extensions.jsc3d:JSC3DRenderer"
+stp = "mfr.extensions.jsc3d:JSC3DRenderer"
+step = "mfr.extensions.jsc3d:JSC3DRenderer"
+
+
+# pdb
+pdb = "mfr.extensions.pdb:PdbRenderer"
+
+# pdf
+pdf = "mfr.extensions.pdf:PdfRenderer"
+
+# rst
+rst = "mfr.extensions.rst:RstRenderer"
+
+# svg
+# .svg = mfr.extensions.svg:SvgRenderer
+
+# tabular
+csv = "mfr.extensions.tabular:TabularRenderer"
+tsv = "mfr.extensions.tabular:TabularRenderer"
+xls = "mfr.extensions.tabular:TabularRenderer"
+xlsx = "mfr.extensions.tabular:TabularRenderer"
+dta = "mfr.extensions.tabular:TabularRenderer"
+mat = "mfr.extensions.tabular:TabularRenderer"
+sav = "mfr.extensions.tabular:TabularRenderer"
+#.ods = "mfr.extensions.tabular:TabularRenderer"
+
+# unoconv
+# .bib = mfr.extensions.unoconv:UnoconvRenderer
+# .bmp = mfr.extensions.unoconv:UnoconvRenderer
+# .csv = mfr.extensions.unoconv:UnoconvRenderer
+dbf = "mfr.extensions.unoconv:UnoconvRenderer"
+dif = "mfr.extensions.unoconv:UnoconvRenderer"
+doc = "mfr.extensions.unoconv:UnoconvRenderer"
+docx = "mfr.extensions.unoconv:UnoconvRenderer"
+emf = "mfr.extensions.unoconv:UnoconvRenderer"
+eps = "mfr.extensions.unoconv:UnoconvRenderer"
+fodg = "mfr.extensions.unoconv:UnoconvRenderer"
+fodp = "mfr.extensions.unoconv:UnoconvRenderer"
+fods = "mfr.extensions.unoconv:UnoconvRenderer"
+fodt = "mfr.extensions.unoconv:UnoconvRenderer"
+# .gif = "mfr.extensions.unoconv:UnoconvRenderer"
+# .html = "mfr.extensions.unoconv:UnoconvRenderer"
+# .jpg = "mfr.extensions.unoconv:UnoconvRenderer"
+# .ltx = "mfr.extensions.unoconv:UnoconvRenderer"
+met = "mfr.extensions.unoconv:UnoconvRenderer"
+odd = "mfr.extensions.unoconv:UnoconvRenderer"
+odg = "mfr.extensions.unoconv:UnoconvRenderer"
+odp = "mfr.extensions.unoconv:UnoconvRenderer"
+ods = "mfr.extensions.unoconv:UnoconvRenderer"
+odt = "mfr.extensions.unoconv:UnoconvRenderer"
+otg = "mfr.extensions.unoconv:UnoconvRenderer"
+otp = "mfr.extensions.unoconv:UnoconvRenderer"
+ots = "mfr.extensions.unoconv:UnoconvRenderer"
+ott = "mfr.extensions.unoconv:UnoconvRenderer"
+pbm = "mfr.extensions.unoconv:UnoconvRenderer"
+pct = "mfr.extensions.unoconv:UnoconvRenderer"
+# .pdb = "mfr.extensions.unoconv:UnoconvRenderer"
+# .pdf = "mfr.extensions.unoconv:UnoconvRenderer"
+pgm = "mfr.extensions.unoconv:UnoconvRenderer"
+# .png = "mfr.extensions.unoconv:UnoconvRenderer"
+pot = "mfr.extensions.unoconv:UnoconvRenderer"
+potm = "mfr.extensions.unoconv:UnoconvRenderer"
+ppm = "mfr.extensions.unoconv:UnoconvRenderer"
+pps = "mfr.extensions.unoconv:UnoconvRenderer"
+ppt = "mfr.extensions.unoconv:UnoconvRenderer"
+pptx = "mfr.extensions.unoconv:UnoconvRenderer"
+psw = "mfr.extensions.unoconv:UnoconvRenderer"
+pwp = "mfr.extensions.unoconv:UnoconvRenderer"
+pxl = "mfr.extensions.unoconv:UnoconvRenderer"
+ras = "mfr.extensions.unoconv:UnoconvRenderer"
+rtf = "mfr.extensions.unoconv:UnoconvRenderer"
+sda = "mfr.extensions.unoconv:UnoconvRenderer"
+sdc = "mfr.extensions.unoconv:UnoconvRenderer"
+sdd = "mfr.extensions.unoconv:UnoconvRenderer"
+sdw = "mfr.extensions.unoconv:UnoconvRenderer"
+slk = "mfr.extensions.unoconv:UnoconvRenderer"
+stc = "mfr.extensions.unoconv:UnoconvRenderer"
+std = "mfr.extensions.unoconv:UnoconvRenderer"
+sti = "mfr.extensions.unoconv:UnoconvRenderer"
+stw = "mfr.extensions.unoconv:UnoconvRenderer"
+svg = "mfr.extensions.unoconv:UnoconvRenderer"
+svm = "mfr.extensions.unoconv:UnoconvRenderer"
+# Renders junk at the moment
+# .swf = mfr.extensions.unoconv:UnoconvRenderer
+sxc = "mfr.extensions.unoconv:UnoconvRenderer"
+sxd = "mfr.extensions.unoconv:UnoconvRenderer"
+sxi = "mfr.extensions.unoconv:UnoconvRenderer"
+sxw = "mfr.extensions.unoconv:UnoconvRenderer"
+# .tiff = "mfr.extensions.unoconv:UnoconvRenderer"
+# .txt = "mfr.extensions.unoconv:UnoconvRenderer"
+uop = "mfr.extensions.unoconv:UnoconvRenderer"
+uos = "mfr.extensions.unoconv:UnoconvRenderer"
+uot = "mfr.extensions.unoconv:UnoconvRenderer"
+vor = "mfr.extensions.unoconv:UnoconvRenderer"
+wmf = "mfr.extensions.unoconv:UnoconvRenderer"
+wps = "mfr.extensions.unoconv:UnoconvRenderer"
+# .xhtml = "mfr.extensions.unoconv:UnoconvRenderer"
+# .xls = "mfr.extensions.unoconv:UnoconvRenderer"
+# .xlsx = "mfr.extensions.unoconv:UnoconvRenderer"
+xlt = "mfr.extensions.unoconv:UnoconvRenderer"
+# .xml = "mfr.extensions.unoconv:UnoconvRenderer"
+xpm = "mfr.extensions.unoconv:UnoconvRenderer"
+
+# video
+mp4 = "mfr.extensions.video:VideoRenderer"
+m4v = "mfr.extensions.video:VideoRenderer"
+# Unable to support at this time
+#.avi = mfr.extensions.video:VideoRenderer
+ogv = "mfr.extensions.video:VideoRenderer"
+#.wmv = mfr.extensions.video:VideoRenderer
+webm = "mfr.extensions.video:VideoRenderer"
+
+# jamovi
+omv = "mfr.extensions.jamovi:JamoviRenderer"
+
+# JASP
+jasp = "mfr.extensions.jasp:JASPRenderer"
+
+# Zip
+zip = "mfr.extensions.zip:ZipRenderer"
+
+[tool.black]
+line-length = 88
+target-version = ["py313"]
+include = '\.pyi?$'
+exclude = '''
+/(
+ \.venv
+ |\.eggs
+ |_build
+ |build
+ |dist
+ |mfr\.egg-info
+)/
+'''
+
+[tool.isort]
+profile = "black"
+line_length = 88
+known_first_party = ["mfr", "tests"]
+default_section = "THIRDPARTY"
+multi_line_output = 3
+include_trailing_comma = true
+force_grid_wrap = 0
+combine_as_imports = true
+skip = ["mfr.egg-info", ".venv"]
+
+[tool.ruff]
+target-version = "py313"
+line-length = 88
+extend-select = [
+ "E",
+ "F",
+ "C90",
+ "I",
+ "B",
+]
+extend-ignore = [
+ "E203"
+]
+exclude = [
+ "mfr.egg-info",
+ ".venv",
+ "build",
+ "dist",
+ "ipynb"
+]
\ No newline at end of file
diff --git a/readthedocs.yml b/readthedocs.yml
index a1949e981..ecc278a09 100644
--- a/readthedocs.yml
+++ b/readthedocs.yml
@@ -1,3 +1,18 @@
-requirements_file: doc-requirements.txt
-python:
- setup_py_install: true
+version: 2
+
+build:
+ os: ubuntu-24.04
+ tools:
+ python: "3.13"
+ jobs:
+ post_create_environment:
+ - pip install poetry
+ post_install:
+ - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --with docs
+
+sphinx:
+ configuration: docs/conf.py
+
+formats:
+ - pdf
+ - epub
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 575639416..000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-aiohttp==0.18.4
-chardet==2.3.0
-furl==0.4.2
-humanfriendly==2.1
-invoke==0.13.0
-mako==1.0.1
-raven==5.27.0
-setuptools==37.0.0
-stevedore==1.2.0
-tornado==4.3
-
-# WaterButler
-git+https://github.com/CenterForOpenScience/waterbutler.git@0.38.6#egg=waterbutler
-agent==0.1.2
-google-auth==1.4.1
-
-# CodePygments
-Pygments==2.12.0
-
-# Docx
-#git+https://github.com/jsocol/bleach.git
-pydocx==0.7.0
-
-# Image
-olefile==0.44
-Pillow==4.3.0
-psd-tools==1.4
-
-# IPython
-ipython==5.2.2
-nbconvert==4.2.0
-nbformat==4.1.0
-traitlets==4.2.2
-jsonschema==2.4.0
-jinja2==2.10.1
-mistune==0.8.1
-
-# Pdf
-reportlab==3.6.5
-
-# Pptx
-# python-pptx==0.5.7
-
-# Rst
-docutils==0.12
-
-# Tabular
-pandas==0.25.1
-xlrd==1.0.0
-h5py==2.7.0
-scipy==0.19.1
-
-# Md
-markdown==2.6.2
-
-certifi==2021.5.30
diff --git a/setup.cfg b/setup.cfg
index f4a03a181..950c7f901 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -10,5 +10,5 @@ ignore = E501,E127,E128,E265,E301,E302,F403,E731
max-line-length = 100
exclude = .ropeproject,tests/*,src/*,env,venv,node_modules/*
-[pytest]
+[tool:pytest]
norecursedirs = .* build CVS _darcs {arch} *.egg venv node_modules/*
diff --git a/setup.py b/setup.py
deleted file mode 100755
index 6feaa350b..000000000
--- a/setup.py
+++ /dev/null
@@ -1,820 +0,0 @@
-from setuptools import setup, find_packages
-
-
-def parse_requirements(requirements):
- with open(requirements) as f:
- return [l.strip('\n') for l in f if l.strip('\n') and not l.startswith('#')]
-
-
-requirements = parse_requirements('requirements.txt')
-
-# Taken from option 3 of https://packaging.python.org/guides/single-sourcing-package-version/
-version = {}
-with open('mfr/version.py') as fp:
- exec(fp.read(), version)
-
-setup(
- name='mfr',
- version=version['__version__'],
- namespace_packages=['mfr', 'mfr.extensions', 'mfr.providers'],
- description='Modular File Renderer',
- author='Center for Open Science',
- author_email='contact@cos.io',
- url='https://github.com/CenterForOpenScience/modular-file-renderer',
- packages=find_packages(exclude=("tests*", )),
- package_dir={'mfr': 'mfr'},
- include_package_data=True,
- # install_requires=requirements,
- zip_safe=False,
- classifiers=[
- 'Natural Language :: English',
- 'Intended Audience :: Developers',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.6',
- 'Development Status :: 5 - Production/Stable',
- 'License :: OSI Approved :: Apache Software License',
- ],
- provides=[
- 'mfr.extensions',
- 'mfr.providers',
- ],
- entry_points={
- 'mfr.providers': [
- 'http = mfr.providers.http:HttpProvider',
- 'osf = mfr.providers.osf:OsfProvider',
- ],
- 'mfr.exporters': [
- # google docs
- '.gdraw = mfr.extensions.image:ImageExporter',
- '.gdoc = mfr.extensions.unoconv:UnoconvExporter',
- '.gsheet = mfr.extensions.unoconv:UnoconvExporter',
- '.gslides = mfr.extensions.unoconv:UnoconvExporter',
-
- # image
- '.jpg = mfr.extensions.image:ImageExporter',
- '.jpeg = mfr.extensions.image:ImageExporter',
- '.png = mfr.extensions.image:ImageExporter',
- '.bmp = mfr.extensions.image:ImageExporter',
- '.gif = mfr.extensions.image:ImageExporter',
- '.psd = mfr.extensions.image:ImageExporter',
- '.tif = mfr.extensions.pdf:PdfExporter',
- '.tiff = mfr.extensions.pdf:PdfExporter',
-
- # jsc3d
- '.stp = mfr.extensions.jsc3d:JSC3DExporter',
- '.step = mfr.extensions.jsc3d:JSC3DExporter',
-
- # unoconv
- # '.bib = mfr.extensions.unoconv:UnoconvExporter',
- # '.bmp = mfr.extensions.unoconv:UnoconvExporter',
- # '.csv = mfr.extensions.unoconv:UnoconvExporter',
- '.dbf = mfr.extensions.unoconv:UnoconvExporter',
- '.dif = mfr.extensions.unoconv:UnoconvExporter',
- '.doc = mfr.extensions.unoconv:UnoconvExporter',
- '.docx = mfr.extensions.unoconv:UnoconvExporter',
- '.emf = mfr.extensions.unoconv:UnoconvExporter',
- '.eps = mfr.extensions.unoconv:UnoconvExporter',
- '.fodg = mfr.extensions.unoconv:UnoconvExporter',
- '.fodp = mfr.extensions.unoconv:UnoconvExporter',
- '.fods = mfr.extensions.unoconv:UnoconvExporter',
- '.fodt = mfr.extensions.unoconv:UnoconvExporter',
- # '.gif = mfr.extensions.unoconv:UnoconvExporter',
- # '.html = mfr.extensions.unoconv:UnoconvExporter',
- # '.jpg = mfr.extensions.unoconv:UnoconvExporter',
- # '.ltx = mfr.extensions.unoconv:UnoconvExporter',
- '.met = mfr.extensions.unoconv:UnoconvExporter',
- '.odd = mfr.extensions.unoconv:UnoconvExporter',
- '.odg = mfr.extensions.unoconv:UnoconvExporter',
- '.odp = mfr.extensions.unoconv:UnoconvExporter',
- '.ods = mfr.extensions.unoconv:UnoconvExporter',
- '.odt = mfr.extensions.unoconv:UnoconvExporter',
- '.otg = mfr.extensions.unoconv:UnoconvExporter',
- '.otp = mfr.extensions.unoconv:UnoconvExporter',
- '.ots = mfr.extensions.unoconv:UnoconvExporter',
- '.ott = mfr.extensions.unoconv:UnoconvExporter',
- '.pbm = mfr.extensions.unoconv:UnoconvExporter',
- '.pct = mfr.extensions.unoconv:UnoconvExporter',
- # '.pdb = mfr.extensions.unoconv:UnoconvExporter',
- # '.pdf = mfr.extensions.unoconv:UnoconvExporter',
- '.pgm = mfr.extensions.unoconv:UnoconvExporter',
- # '.png = mfr.extensions.unoconv:UnoconvExporter',
- '.pot = mfr.extensions.unoconv:UnoconvExporter',
- '.potm = mfr.extensions.unoconv:UnoconvExporter',
- '.ppm = mfr.extensions.unoconv:UnoconvExporter',
- '.pps = mfr.extensions.unoconv:UnoconvExporter',
- '.ppt = mfr.extensions.unoconv:UnoconvExporter',
- '.pptx = mfr.extensions.unoconv:UnoconvExporter',
- '.psw = mfr.extensions.unoconv:UnoconvExporter',
- '.pwp = mfr.extensions.unoconv:UnoconvExporter',
- '.pxl = mfr.extensions.unoconv:UnoconvExporter',
- '.ras = mfr.extensions.unoconv:UnoconvExporter',
- '.rtf = mfr.extensions.unoconv:UnoconvExporter',
- '.sda = mfr.extensions.unoconv:UnoconvExporter',
- '.sdc = mfr.extensions.unoconv:UnoconvExporter',
- '.sdd = mfr.extensions.unoconv:UnoconvExporter',
- '.sdw = mfr.extensions.unoconv:UnoconvExporter',
- '.slk = mfr.extensions.unoconv:UnoconvExporter',
- '.stc = mfr.extensions.unoconv:UnoconvExporter',
- '.std = mfr.extensions.unoconv:UnoconvExporter',
- '.sti = mfr.extensions.unoconv:UnoconvExporter',
- '.stw = mfr.extensions.unoconv:UnoconvExporter',
- '.svg = mfr.extensions.unoconv:UnoconvExporter',
- '.svm = mfr.extensions.unoconv:UnoconvExporter',
- # Renders junk at the moment
- # '.swf = mfr.extensions.unoconv:UnoconvExporter',
- '.sxc = mfr.extensions.unoconv:UnoconvExporter',
- '.sxd = mfr.extensions.unoconv:UnoconvExporter',
- '.sxi = mfr.extensions.unoconv:UnoconvExporter',
- '.sxw = mfr.extensions.unoconv:UnoconvExporter',
- # '.tiff = mfr.extensions.unoconv:UnoconvExporter',
- # '.txt = mfr.extensions.unoconv:UnoconvExporter',
- '.uop = mfr.extensions.unoconv:UnoconvExporter',
- '.uos = mfr.extensions.unoconv:UnoconvExporter',
- '.uot = mfr.extensions.unoconv:UnoconvExporter',
- '.vor = mfr.extensions.unoconv:UnoconvExporter',
- '.wmf = mfr.extensions.unoconv:UnoconvExporter',
- '.wps = mfr.extensions.unoconv:UnoconvExporter',
- # '.xhtml = mfr.extensions.unoconv:UnoconvExporter',
- # '.xls = mfr.extensions.unoconv:UnoconvExporter',
- # '.xlsx = mfr.extensions.unoconv:UnoconvExporter',
- '.xlt = mfr.extensions.unoconv:UnoconvExporter',
- # '.xml = mfr.extensions.unoconv:UnoconvExporter',
- '.xpm = mfr.extensions.unoconv:UnoconvExporter',
- ],
- 'mfr.renderers': [
- # audio
- '.mp3 = mfr.extensions.audio:AudioRenderer',
- '.ogg = mfr.extensions.audio:AudioRenderer',
- '.wav = mfr.extensions.audio:AudioRenderer',
-
- # code pygments
- 'none = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.1 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.2 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.3 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.4 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.5 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.6 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.6pm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.6pl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.7 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.abap = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ada = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.adb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ads = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.agda = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ahk = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ahkl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.aj = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.als = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.amw = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.anl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.apl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.applescript = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.arexx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.as = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.asax = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ascx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ashx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.asm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.asmx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.aspx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.asy = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.at = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.au3 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.aux = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.awk = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.axd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.b = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bas = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bash = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bat = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bed = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.befunge = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bib = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bmx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.boa = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.boo = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.boxs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bro = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bst = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bug = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.c = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.c++ = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.c++-objdump = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.c-objdump = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cbl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cdf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cmdi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ceylon = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cfc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cfg = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cfm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cfml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.chai = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.chpl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cirru = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.clay = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.clj = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cljs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cls = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cmake = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cmd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cob = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.coffee = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cpp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cpp-objdump = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cpy = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.croc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cry = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.csh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.csl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.css = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.css.in = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cu = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cuh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cw = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cxx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cxx-objdump = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cyp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.cypher = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.d = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.d-objdump = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.darcspatch = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.dart = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.decls = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.def = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.dg = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.di = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.diff = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.docker = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.dpatch = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.dtd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.duby = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.duel = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.dyl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.dylan = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.dylan-console = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.e = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.eaf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ebnf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ebuild = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ec = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ecl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.eclass = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.eh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.el = mfr.extensions.codepygments:CodePygmentsRenderer',
- # '.eps = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.eqn = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.erl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.erl-sh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.es = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.escript = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.evoque = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ex = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.exs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.f = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.f90 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.factor = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fan = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fancypack = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fas = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fasta = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.feature = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fhtml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.flx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.flxh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.frag = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fsi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fun = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.fy = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.g = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gap = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gdc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gdt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gemspec = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.geo = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.go = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.golo = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.groovy = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gsp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gst = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gsx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.h = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.h++ = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.haml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.handlebars = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hbs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hdp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hpp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hrl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.htm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.html = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hxml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hxsl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hxx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hy = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.hyb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.i = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.i6t = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.i7x = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.idc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.idr = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ijm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ik = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.inc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.inf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ini = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ino = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.inp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.intr = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.io = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ipf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.iqx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.j = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.jade = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.jag = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.java = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.jbst = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.jl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.js = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.js.in = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.json = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.jsonld = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.jsp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.jst = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.jsx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.kal = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.kid = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.kk = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.kki = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ksh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.kt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lagda = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lasso = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lasso[89] = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lcry = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lean = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lgs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lgt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lhs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lid = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lidr = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.liquid = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lisp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.list = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ll = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.log = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.logtalk = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ls = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lsl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lsp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lss = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lst = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ltx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lua = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.lyx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.m = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ma = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mak = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.man = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mao = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.maql = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mask = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mdp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mhtml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mk = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mli = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mll = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mly = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mo = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mod = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.monkey = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.moo = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.moon = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mq4 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mq5 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mqh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.msc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mu = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.mxml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.myt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.n = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nbp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nex = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ni = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nim = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nimrod = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nit = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nix = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nlogo = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nqp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ns2 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nsh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.nsi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.objdump = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.objdump-intel = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ooc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.opa = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.opensesame = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.org = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.p = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.p6 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.p6l = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.p6m = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pan = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pas = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.patch = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.php = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.php[345] = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.phtml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pig = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pike = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pl6 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.plot = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.plt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pm6 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pmod = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.po = mfr.extensions.codepygments:CodePygmentsRenderer',
- # '.pot = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pov = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.praat = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.prg = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.prj = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pro = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.prolog = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.properties = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.proto = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ps = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.psydat = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.psyexp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ps1 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.psm1 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pwn = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pxd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pxi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.py = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.py3tb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pypylog = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pytb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pyw = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pyx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.pzfx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.qml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.qsf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.r = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.r3 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rake = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rbw = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rbx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rdf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.reb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.red = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.reds = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.reg = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rest = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rex = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rexx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rhtml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ris = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rkt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rktd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rktl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rm5 = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rnw = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.robot = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rout = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rpf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rq = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rql = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rs = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rsl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rss = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rvt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rx = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.s = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sage = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sass = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.scad = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.scala = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.scaml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sce = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sci = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sch = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.scm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.scss = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sdf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sh-session = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.shell-session = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sig = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.slim = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sls = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.smali = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.smcl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.snobol = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sparql = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.spec = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.spt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sql = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sqlite3-console = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ss = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ssp = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.st = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.stan = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sty = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sv = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.svh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.swg = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.swift = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.t = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tab = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tac = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tcl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tcsh = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tea = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tem = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tex = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.textgrid = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.thy = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tmpl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.toc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.todotxt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tpl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tre = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.treetop = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ts = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tst = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.tt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.ttl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.twig = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.txt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rmd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.do = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sas = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.sps = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.u = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.umbrella = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.v = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vala = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vapi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vark = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vb = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vert = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vhd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vhdl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vim = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vmrk = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vtk = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vtt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.weechatlog = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.wlua = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.wndpos = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.wsdl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.wsf = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.x = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xhtml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xmi = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xpl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xq = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xql = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xqm = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xquery = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xqy = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xsd = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xsl = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xslt = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xtend = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.xul.in = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.yaml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.yml = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.zep = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.*config.in* = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.renviron = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rhistory = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.rprofile = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.bash_* = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.bashrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.exrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.gvimrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.htaccess = mfr.extensions.codepygments:CodePygmentsRenderer',
- '.vimrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.cmakelists.txt = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.dockerfile = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.gnumakefile = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.kconfig = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.makefile = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.makefile.* = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.pkgbuild = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.rakefile = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.sconscript = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.sconstruct = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'._exrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'._gvimrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'._vimrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.apache.conf = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.apache2.conf = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.autodelegate = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.autohandler = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.bash_* = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.bashrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.control = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.dhandler = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.external.in* = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.gvimrc = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.makefile = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.sources.list = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.squid.conf = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.standard-modules.in = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.todo.txt = mfr.extensions.codepygments:CodePygmentsRenderer',
- #'.vimrc' = mfr.extensions.codepygments:CodePygmentsRenderer',
-
- # docx
- # '.docx = mfr.extensions.docx:DocxRenderer',
-
- # google docs
- '.gdraw = mfr.extensions.image:ImageRenderer',
- '.gdoc = mfr.extensions.unoconv:UnoconvRenderer',
- '.gsheet = mfr.extensions.tabular:TabularRenderer',
- '.gslides = mfr.extensions.unoconv:UnoconvRenderer',
-
- # image
- '.bmp = mfr.extensions.image:ImageRenderer',
- '.jpg = mfr.extensions.image:ImageRenderer',
- '.jpeg = mfr.extensions.image:ImageRenderer',
- '.gif = mfr.extensions.image:ImageRenderer',
- '.ico = mfr.extensions.image:ImageRenderer',
- '.png = mfr.extensions.image:ImageRenderer',
- '.psd = mfr.extensions.image:ImageRenderer',
- '.tif = mfr.extensions.pdf:PdfRenderer',
- '.tiff = mfr.extensions.pdf:PdfRenderer',
-
- # ipynb
- '.ipynb = mfr.extensions.ipynb:IpynbRenderer',
-
- # md
- '.md = mfr.extensions.md:MdRenderer',
- '.markdown = mfr.extensions.md:MdRenderer',
-
- # jsc3d
- '.3ds = mfr.extensions.jsc3d:JSC3DRenderer',
- '.ctm = mfr.extensions.jsc3d:JSC3DRenderer',
- '.obj = mfr.extensions.jsc3d:JSC3DRenderer',
- '.stl = mfr.extensions.jsc3d:JSC3DRenderer',
- '.stp = mfr.extensions.jsc3d:JSC3DRenderer',
- '.step = mfr.extensions.jsc3d:JSC3DRenderer',
-
-
- # pdb
- '.pdb = mfr.extensions.pdb:PdbRenderer',
-
- # pdf
- '.pdf = mfr.extensions.pdf:PdfRenderer',
-
- # rst
- '.rst = mfr.extensions.rst:RstRenderer',
-
- # svg
- # '.svg = mfr.extensions.svg:SvgRenderer',
-
- # tabular
- '.csv = mfr.extensions.tabular:TabularRenderer',
- '.tsv = mfr.extensions.tabular:TabularRenderer',
- '.xls = mfr.extensions.tabular:TabularRenderer',
- '.xlsx = mfr.extensions.tabular:TabularRenderer',
- '.dta = mfr.extensions.tabular:TabularRenderer',
- '.mat = mfr.extensions.tabular:TabularRenderer',
- '.sav = mfr.extensions.tabular:TabularRenderer',
- #'.ods = mfr.extensions.tabular:TabularRenderer',
-
- # unoconv
- # '.bib = mfr.extensions.unoconv:UnoconvRenderer',
- # '.bmp = mfr.extensions.unoconv:UnoconvRenderer',
- # '.csv = mfr.extensions.unoconv:UnoconvRenderer',
- '.dbf = mfr.extensions.unoconv:UnoconvRenderer',
- '.dif = mfr.extensions.unoconv:UnoconvRenderer',
- '.doc = mfr.extensions.unoconv:UnoconvRenderer',
- '.docx = mfr.extensions.unoconv:UnoconvRenderer',
- '.emf = mfr.extensions.unoconv:UnoconvRenderer',
- '.eps = mfr.extensions.unoconv:UnoconvRenderer',
- '.fodg = mfr.extensions.unoconv:UnoconvRenderer',
- '.fodp = mfr.extensions.unoconv:UnoconvRenderer',
- '.fods = mfr.extensions.unoconv:UnoconvRenderer',
- '.fodt = mfr.extensions.unoconv:UnoconvRenderer',
- # '.gif = mfr.extensions.unoconv:UnoconvRenderer',
- # '.html = mfr.extensions.unoconv:UnoconvRenderer',
- # '.jpg = mfr.extensions.unoconv:UnoconvRenderer',
- # '.ltx = mfr.extensions.unoconv:UnoconvRenderer',
- '.met = mfr.extensions.unoconv:UnoconvRenderer',
- '.odd = mfr.extensions.unoconv:UnoconvRenderer',
- '.odg = mfr.extensions.unoconv:UnoconvRenderer',
- '.odp = mfr.extensions.unoconv:UnoconvRenderer',
- '.ods = mfr.extensions.unoconv:UnoconvRenderer',
- '.odt = mfr.extensions.unoconv:UnoconvRenderer',
- '.otg = mfr.extensions.unoconv:UnoconvRenderer',
- '.otp = mfr.extensions.unoconv:UnoconvRenderer',
- '.ots = mfr.extensions.unoconv:UnoconvRenderer',
- '.ott = mfr.extensions.unoconv:UnoconvRenderer',
- '.pbm = mfr.extensions.unoconv:UnoconvRenderer',
- '.pct = mfr.extensions.unoconv:UnoconvRenderer',
- # '.pdb = mfr.extensions.unoconv:UnoconvRenderer',
- # '.pdf = mfr.extensions.unoconv:UnoconvRenderer',
- '.pgm = mfr.extensions.unoconv:UnoconvRenderer',
- # '.png = mfr.extensions.unoconv:UnoconvRenderer',
- '.pot = mfr.extensions.unoconv:UnoconvRenderer',
- '.potm = mfr.extensions.unoconv:UnoconvRenderer',
- '.ppm = mfr.extensions.unoconv:UnoconvRenderer',
- '.pps = mfr.extensions.unoconv:UnoconvRenderer',
- '.ppt = mfr.extensions.unoconv:UnoconvRenderer',
- '.pptx = mfr.extensions.unoconv:UnoconvRenderer',
- '.psw = mfr.extensions.unoconv:UnoconvRenderer',
- '.pwp = mfr.extensions.unoconv:UnoconvRenderer',
- '.pxl = mfr.extensions.unoconv:UnoconvRenderer',
- '.ras = mfr.extensions.unoconv:UnoconvRenderer',
- '.rtf = mfr.extensions.unoconv:UnoconvRenderer',
- '.sda = mfr.extensions.unoconv:UnoconvRenderer',
- '.sdc = mfr.extensions.unoconv:UnoconvRenderer',
- '.sdd = mfr.extensions.unoconv:UnoconvRenderer',
- '.sdw = mfr.extensions.unoconv:UnoconvRenderer',
- '.slk = mfr.extensions.unoconv:UnoconvRenderer',
- '.stc = mfr.extensions.unoconv:UnoconvRenderer',
- '.std = mfr.extensions.unoconv:UnoconvRenderer',
- '.sti = mfr.extensions.unoconv:UnoconvRenderer',
- '.stw = mfr.extensions.unoconv:UnoconvRenderer',
- '.svg = mfr.extensions.unoconv:UnoconvRenderer',
- '.svm = mfr.extensions.unoconv:UnoconvRenderer',
- # Renders junk at the moment
- # '.swf = mfr.extensions.unoconv:UnoconvRenderer',
- '.sxc = mfr.extensions.unoconv:UnoconvRenderer',
- '.sxd = mfr.extensions.unoconv:UnoconvRenderer',
- '.sxi = mfr.extensions.unoconv:UnoconvRenderer',
- '.sxw = mfr.extensions.unoconv:UnoconvRenderer',
- # '.tiff = mfr.extensions.unoconv:UnoconvRenderer',
- # '.txt = mfr.extensions.unoconv:UnoconvRenderer',
- '.uop = mfr.extensions.unoconv:UnoconvRenderer',
- '.uos = mfr.extensions.unoconv:UnoconvRenderer',
- '.uot = mfr.extensions.unoconv:UnoconvRenderer',
- '.vor = mfr.extensions.unoconv:UnoconvRenderer',
- '.wmf = mfr.extensions.unoconv:UnoconvRenderer',
- '.wps = mfr.extensions.unoconv:UnoconvRenderer',
- # '.xhtml = mfr.extensions.unoconv:UnoconvRenderer',
- # '.xls = mfr.extensions.unoconv:UnoconvRenderer',
- # '.xlsx = mfr.extensions.unoconv:UnoconvRenderer',
- '.xlt = mfr.extensions.unoconv:UnoconvRenderer',
- # '.xml = mfr.extensions.unoconv:UnoconvRenderer',
- '.xpm = mfr.extensions.unoconv:UnoconvRenderer',
-
- # video
- '.mp4 = mfr.extensions.video:VideoRenderer',
- '.m4v = mfr.extensions.video:VideoRenderer',
- # Unable to support at this time
- #'.avi = mfr.extensions.video:VideoRenderer',
- '.ogv = mfr.extensions.video:VideoRenderer',
- #'.wmv = mfr.extensions.video:VideoRenderer',
- '.webm = mfr.extensions.video:VideoRenderer',
-
- # jamovi
- '.omv = mfr.extensions.jamovi:JamoviRenderer',
-
- # JASP
- '.jasp = mfr.extensions.jasp:JASPRenderer',
-
- # Zip
- '.zip = mfr.extensions.zip:ZipRenderer'
- ]
- },
-)
diff --git a/tasks.py b/tasks.py
index 8280a6f3b..f4f7c2af3 100644
--- a/tasks.py
+++ b/tasks.py
@@ -3,30 +3,24 @@
from invoke import task
WHEELHOUSE_PATH = os.environ.get('WHEELHOUSE')
-CONSTRAINTS_FILE = 'constraints.txt'
@task
-def wheelhouse(ctx, develop=False):
- req_file = 'dev-requirements.txt' if develop else 'requirements.txt'
- cmd = 'pip wheel --find-links={} -r {} --wheel-dir={} -c {}'.format(WHEELHOUSE_PATH, req_file, WHEELHOUSE_PATH, CONSTRAINTS_FILE)
- ctx.run(cmd, pty=True)
+def wheelhouse(ctx, develop=False, pty=True):
+ extras = '--with dev' if develop else ''
+ cmd = f'poetry export --format=requirements.txt {extras} | pip wheel --find-links={WHEELHOUSE_PATH} -r /dev/stdin --wheel-dir={WHEELHOUSE_PATH}'
+ ctx.run(cmd, pty=pty)
@task
-def install(ctx, develop=False):
- ctx.run('python setup.py develop')
- req_file = 'dev-requirements.txt' if develop else 'requirements.txt'
- cmd = 'pip install --upgrade -r {} -c {}'.format(req_file, CONSTRAINTS_FILE)
-
- if WHEELHOUSE_PATH:
- cmd += ' --no-index --find-links={}'.format(WHEELHOUSE_PATH)
- ctx.run(cmd, pty=True)
+def install(ctx, develop=False, pty=True):
+ extras = '--with dev' if develop else ''
+ ctx.run(f'poetry install {extras}', pty=pty)
@task
def flake(ctx):
- ctx.run('flake8 .', pty=True)
+ ctx.run('poetry run flake8 .', pty=True)
@task
@@ -43,14 +37,14 @@ def test(ctx, verbose=False, nocov=False, extension=None, path=None):
# `--extension=` and `--path=` are mutually exclusive options
assert not (extension and path)
if path:
- path = '/{}'.format(path) if path else ''
+ path = f'/{path}' if path else ''
elif extension:
- path = '/extensions/{}/'.format(extension) if extension else ''
+ path = f'/extensions/{extension}/' if extension else ''
else:
path = ''
coverage = ' --cov-report term-missing --cov mfr' if not nocov else ''
verbose = '-v' if verbose else ''
- cmd = 'py.test{} tests{} {}'.format(coverage, path, verbose)
+ cmd = f'poetry run pytest{coverage} tests{path} {verbose}'
ctx.run(cmd, pty=True)
@@ -64,3 +58,15 @@ def server(ctx):
from mfr.server.app import serve
serve()
+
+@task
+def celery(ctx, loglevel='INFO', hostname='%h', concurrency=None):
+ from mfr.tasks.app import app
+ command = ['worker']
+ if loglevel:
+ command.extend(['--loglevel', loglevel])
+ if hostname:
+ command.extend(['--hostname', hostname])
+ if concurrency:
+ command.extend(['--concurrency', concurrency])
+ app.worker_main(command)
diff --git a/tests/extensions/docx/__init__.py b/tests/core/__init__.py
similarity index 100%
rename from tests/extensions/docx/__init__.py
rename to tests/core/__init__.py
diff --git a/tests/core/test_utils.py b/tests/core/test_utils.py
index 7e908e353..fb0f08532 100644
--- a/tests/core/test_utils.py
+++ b/tests/core/test_utils.py
@@ -1,39 +1,57 @@
import pytest
-import pkg_resources
+from importlib.metadata import entry_points
+
+from skimage._shared.testing import parametrize
from mfr.core import utils as mfr_utils
+from mfr.core.utils import fix_name
class TestGetRendererName:
def test_get_renderer_name_explicit_assertions(self):
- assert mfr_utils.get_renderer_name('.jpg') == 'ImageRenderer'
- assert mfr_utils.get_renderer_name('.txt') == 'CodePygmentsRenderer'
- assert mfr_utils.get_renderer_name('.xlsx') == 'TabularRenderer'
- assert mfr_utils.get_renderer_name('.odt') == 'UnoconvRenderer'
- assert mfr_utils.get_renderer_name('.pdf') == 'PdfRenderer'
+ assert mfr_utils.get_renderer_name('jpg') == 'ImageRenderer'
+ assert mfr_utils.get_renderer_name('txt') == 'CodePygmentsRenderer'
+ assert mfr_utils.get_renderer_name('xlsx') == 'TabularRenderer'
+ assert mfr_utils.get_renderer_name('odt') == 'UnoconvRenderer'
+ assert mfr_utils.get_renderer_name('pdf') == 'PdfRenderer'
def test_get_renderer_name(self):
- entry_points = pkg_resources.iter_entry_points(group='mfr.renderers')
- for ep in entry_points:
- expected = ep.attrs[0]
+ for ep in entry_points().select(group='mfr.renderers'):
+ expected = ep.value.split(":")[1].split('.')[0]
assert mfr_utils.get_renderer_name(ep.name) == expected
def test_get_renderer_name_no_entry_point(self):
- assert mfr_utils.get_renderer_name('jpg') == '' # extensions must begin with a period
+ assert mfr_utils.get_renderer_name('.jpg') == '' # extensions must begin with a period
class TestGetExporterName:
def test_get_exporter_name_explicit_assertions(self):
- assert mfr_utils.get_exporter_name('.jpg') == 'ImageExporter'
- assert mfr_utils.get_exporter_name('.odt') == 'UnoconvExporter'
+ assert mfr_utils.get_exporter_name('jpg') == 'ImageExporter'
+ assert mfr_utils.get_exporter_name('odt') == 'UnoconvExporter'
def test_get_exporter_name(self):
- entry_points = pkg_resources.iter_entry_points(group='mfr.exporters')
- for ep in entry_points:
- expected = ep.attrs[0]
+ for ep in entry_points().select(group='mfr.exporters'):
+ expected = ep.value.split(":")[1].split('.')[0]
assert mfr_utils.get_exporter_name(ep.name) == expected
def test_get_exporter_name_no_entry_point(self):
- assert mfr_utils.get_exporter_name('jpg') == '' # extensions must begin with a period
+ assert mfr_utils.get_exporter_name('.jpg') == '' # extensions must begin with a period
+
+@parametrize(
+ "inp, out",
+ [
+ ["jpg", "jpg"],
+ ["c++", "cpp"],
+ ["h++", "hpp"],
+ ["php[345]", "php"],
+ ["lasso[89]", "lasso"],
+ ["css.in", "css"],
+ ["js.in", "js"],
+ ["xul.in", "xul"],
+ ],
+)
+def test_fix_name(inp, out):
+ assert fix_name(inp) == out
+ assert fix_name(f'.{inp}') == out
diff --git a/tests/documentation/test_entrypoints.py b/tests/documentation/test_entrypoints.py
index 88f6bbb35..1ac93f43c 100644
--- a/tests/documentation/test_entrypoints.py
+++ b/tests/documentation/test_entrypoints.py
@@ -1,7 +1,9 @@
import os
import pytest
-import pkg_resources
+from importlib.metadata import entry_points
+
+from mfr.core.utils import fix_name
class TestEntryPoints:
@@ -9,9 +11,9 @@ class TestEntryPoints:
def test_entry_points(self):
parent_dir = os.pardir
- readme_path = os.path.join(os.path.dirname((parent_dir)), 'supportedextensions.md')
- with open(readme_path, 'r') as file:
- readme_ext = [line.strip()[2:] for line in file if '*' in line]
- for ep in pkg_resources.iter_entry_points(group='mfr.renderers'):
+ readme_path = os.path.join(os.path.dirname(parent_dir), 'supportedextensions.md')
+ with open(readme_path) as file:
+ readme_ext = [fix_name(line.strip()[2:]) for line in file if '*' in line]
+ for ep in entry_points().select(group='mfr.renderers'):
if ep.name != 'none':
assert ep.name in readme_ext
diff --git a/tests/extensions/audio/test_renderer.py b/tests/extensions/audio/test_renderer.py
index 6dc344142..7f3317bd7 100644
--- a/tests/extensions/audio/test_renderer.py
+++ b/tests/extensions/audio/test_renderer.py
@@ -26,8 +26,8 @@ def assets_url():
@pytest.fixture
-def export_url():
- return 'http://mfr.osf.io/export?url=' + url()
+def export_url(url):
+ return 'http://mfr.osf.io/export?url=' + url
@pytest.fixture
@@ -38,9 +38,9 @@ def renderer(metadata, file_path, url, assets_url, export_url):
class TestAudioRenderer:
def test_render_audio(self, renderer, url):
- body = renderer.render()
+ body = renderer._render()
assert '