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/scripts/ci/render-trivy-report.py b/.github/scripts/ci/render-trivy-report.py new file mode 100644 index 000000000..bd188faae --- /dev/null +++ b/.github/scripts/ci/render-trivy-report.py @@ -0,0 +1,128 @@ +import argparse +import json +from collections import Counter + + +SEVERITIES = ('CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'UNKNOWN') +SEVERITY_ORDER = {severity: index for index, severity in enumerate(SEVERITIES)} +COMMENT_MARKER = '' + + +def markdown_escape(value): + return str(value or '-').replace('\n', ' ').replace('|', '\\|') + + +def get_vulnerabilities(report): + return [ + vulnerability + for result in report.get('Results', []) + for vulnerability in result.get('Vulnerabilities') or [] + ] + + +def render_report(report, image, commit, run_url): + vulnerabilities = get_vulnerabilities(report) + counts = Counter( + vulnerability.get('Severity', 'UNKNOWN').upper() + for vulnerability in vulnerabilities + ) + fixable_counts = Counter( + vulnerability.get('Severity', 'UNKNOWN').upper() + for vulnerability in vulnerabilities + if vulnerability.get('FixedVersion') + ) + + lines = [ + COMMENT_MARKER, + '## Container image vulnerability scan', + '', + f'- Image: `{markdown_escape(image)}`', + f'- Commit: [`{commit[:12]}`]({run_url.rsplit("/actions/runs/", 1)[0]}/commit/{commit})', + f'- Workflow run: [details]({run_url})', + f'- Findings: **{len(vulnerabilities)}** ' + f'({sum(fixable_counts.values())} with a fix available)', + '', + '| Severity | Total | Fix available |', + '| --- | ---: | ---: |', + ] + for severity in SEVERITIES: + lines.append( + f'| {severity} | {counts[severity]} | {fixable_counts[severity]} |', + ) + + important = sorted( + ( + vulnerability + for vulnerability in vulnerabilities + if vulnerability.get('Severity', 'UNKNOWN').upper() in {'CRITICAL', 'HIGH'} + ), + key=lambda vulnerability: ( + SEVERITY_ORDER.get( + vulnerability.get('Severity', 'UNKNOWN').upper(), + len(SEVERITIES), + ), + vulnerability.get('VulnerabilityID', ''), + vulnerability.get('PkgName', ''), + ), + ) + lines.extend([ + '', + '### High-priority findings', + '', + ]) + if important: + lines.extend([ + '| Severity | Vulnerability | Package | Installed | Fixed |', + '| --- | --- | --- | --- | --- |', + ]) + for vulnerability in important[:20]: + lines.append( + '| {severity} | {identifier} | {package} | {installed} | {fixed} |'.format( + severity=markdown_escape(vulnerability.get('Severity')), + identifier=markdown_escape(vulnerability.get('VulnerabilityID')), + package=markdown_escape(vulnerability.get('PkgName')), + installed=markdown_escape(vulnerability.get('InstalledVersion')), + fixed=markdown_escape(vulnerability.get('FixedVersion')), + ), + ) + if len(important) > 20: + lines.extend([ + '', + f'_Showing 20 of {len(important)} HIGH/CRITICAL findings._', + ]) + else: + lines.append('No HIGH or CRITICAL findings were detected.') + + lines.extend([ + '', + '> This scan is currently reporting-only and establishes the vulnerability baseline.', + '> The complete JSON and SARIF reports are attached to the workflow run.', + '', + ]) + return '\n'.join(lines) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--input', required=True) + parser.add_argument('--output', required=True) + parser.add_argument('--image', required=True) + parser.add_argument('--commit', required=True) + parser.add_argument('--run-url', required=True) + args = parser.parse_args() + + with open(args.input, encoding='utf-8') as report_file: + report = json.load(report_file) + + rendered = render_report( + report, + image=args.image, + commit=args.commit, + run_url=args.run_url, + ) + with open(args.output, 'w', encoding='utf-8') as output_file: + output_file.write(rendered) + + +if __name__ == '__main__': + main() diff --git a/.github/scripts/ci/run-tests.sh b/.github/scripts/ci/run-tests.sh index d1003c623..f98be09bf 100644 --- a/.github/scripts/ci/run-tests.sh +++ b/.github/scripts/ci/run-tests.sh @@ -11,17 +11,32 @@ TEST_BUILD="$1" REPO_ROOT=$(git rev-parse --show-toplevel) cd "$REPO_ROOT" +NETWORK="mfr-tests-$$" +docker network create "$NETWORK" +cleanup() { + docker rm -f mfr-unoserver >/dev/null 2>&1 || true + docker network rm "$NETWORK" >/dev/null 2>&1 || true +} +trap cleanup EXIT + +# Start the LibreOffice conversion server so the unoconv exporter tests run against the real thing +docker run -d --name mfr-unoserver --network "$NETWORK" "${MFR_UNOSERVER_IMAGE}" +for _ in $(seq 1 60); do + if docker logs mfr-unoserver 2>&1 | grep -q 'INFO:unoserver:Started.'; then + break + fi + sleep 1 +done +docker logs mfr-unoserver 2>&1 | grep -q 'INFO:unoserver:Started.' + read -r -d '' container_script <<'BASH' || true -export WHEELHOUSE=$HOME/wheelhouse -pip install --upgrade pip -pip install setuptools==37.0.0 -pip install wheel==0.26.0 -pip install invoke==0.13.0 -invoke wheelhouse --develop -invoke install --develop +poetry install --without=docs --with=dev invoke test BASH docker run --rm -t \ + --network "$NETWORK" \ -e TEST_BUILD="$TEST_BUILD" \ - ${MFR_TEST_IMAGE} bash -lc "$container_script" + -e MFR_UNOSERVER_TESTS=1 \ + -e UNOSERVER_EXTENSION_CONFIG_HOST=mfr-unoserver \ + ${MFR_TEST_IMAGE} bash -c "$container_script" diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 328090d7f..86694e5b0 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -14,6 +14,8 @@ jobs: contents: read outputs: image: ${{ steps.meta.outputs.image }} + build_image: ${{ steps.meta.outputs.build_image }} + unoserver_image: ${{ steps.meta.outputs.unoserver_image }} steps: - name: Checkout uses: actions/checkout@v4 @@ -23,10 +25,26 @@ jobs: run: | docker build -t rdm-mfr-test:${{ github.sha }} -f ./Dockerfile . + - name: Build Docker image (build stage, used for unit tests) + run: | + docker build --target build -t rdm-mfr-build:${{ github.sha }} -f ./Dockerfile . + + - name: Build Docker image (unoserver) + run: | + docker build -t rdm-unoserver-test:${{ github.sha }} -f ./Dockerfile.unoserver . + - name: Save Docker image run: | docker save rdm-mfr-test:${{ github.sha }} -o /tmp/rdm-mfr-image.tar + - name: Save Docker image (build stage) + run: | + docker save rdm-mfr-build:${{ github.sha }} -o /tmp/rdm-mfr-build-image.tar + + - name: Save Docker image (unoserver) + run: | + docker save rdm-unoserver-test:${{ github.sha }} -o /tmp/rdm-unoserver-image.tar + - name: Upload Docker image artifact uses: actions/upload-artifact@v4 with: @@ -34,9 +52,153 @@ jobs: path: /tmp/rdm-mfr-image.tar retention-days: 1 + - name: Upload Docker image artifact (build stage) + uses: actions/upload-artifact@v4 + with: + name: rdm-mfr-build-image + path: /tmp/rdm-mfr-build-image.tar + retention-days: 1 + + - name: Upload Docker image artifact (unoserver) + uses: actions/upload-artifact@v4 + with: + name: rdm-unoserver-image + path: /tmp/rdm-unoserver-image.tar + retention-days: 1 + - name: Export image reference id: meta - run: echo "image=rdm-mfr-test:${{ github.sha }}" >> "$GITHUB_OUTPUT" + run: | + echo "image=rdm-mfr-test:${{ github.sha }}" >> "$GITHUB_OUTPUT" + echo "build_image=rdm-mfr-build:${{ github.sha }}" >> "$GITHUB_OUTPUT" + echo "unoserver_image=rdm-unoserver-test:${{ github.sha }}" >> "$GITHUB_OUTPUT" + + scan-image: + runs-on: ubuntu-latest + needs: build-image + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + target: + - name: mfr + artifact: rdm-mfr-image + image: ${{ needs.build-image.outputs.image }} + - name: unoserver + artifact: rdm-unoserver-image + image: ${{ needs.build-image.outputs.unoserver_image }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download Docker image artifact + uses: actions/download-artifact@v4 + with: + name: ${{ matrix.target.artifact }} + path: /tmp + + - name: Scan Docker image with Trivy + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 + with: + scan-type: image + input: /tmp/${{ matrix.target.artifact }}.tar + scanners: vuln + vuln-type: os,library + format: json + output: trivy-results.json + exit-code: '0' + list-all-pkgs: 'true' + + - name: Convert Trivy report to SARIF + env: + TRIVY_SCANNERS: '' + run: | + trivy convert \ + --format sarif \ + --output trivy-results.sarif \ + trivy-results.json + + - name: Render vulnerability summary + env: + IMAGE: ${{ matrix.target.image }} + COMMIT: ${{ github.sha }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + python3 .github/scripts/ci/render-trivy-report.py \ + --input trivy-results.json \ + --output trivy-report.md \ + --image "$IMAGE" \ + --commit "$COMMIT" \ + --run-url "$RUN_URL" + tee -a "$GITHUB_STEP_SUMMARY" < trivy-report.md + + - name: Upload vulnerability reports + uses: actions/upload-artifact@v4 + with: + name: trivy-image-scan-${{ matrix.target.name }} + path: | + trivy-results.json + trivy-results.sarif + trivy-report.md + retention-days: 14 + + - name: Upload SARIF to GitHub Code Scanning + if: >- + github.event_name != 'pull_request' || + github.event.pull_request.head.repo.full_name == github.repository + uses: github/codeql-action/upload-sarif@bce182f857edf1feab116e9795a3393d21977282 # v4 + with: + sarif_file: trivy-results.sarif + category: trivy-container-image-${{ matrix.target.name }} + + comment-image-scan: + runs-on: ubuntu-latest + needs: scan-image + if: >- + github.event_name == 'pull_request' && + github.event.pull_request.head.repo.full_name == github.repository + permissions: + actions: read + contents: read + issues: write + pull-requests: write + steps: + - name: Download vulnerability summaries + uses: actions/download-artifact@v4 + with: + pattern: trivy-image-scan-* + path: reports + + - name: Combine summaries + run: | + set -euo pipefail + cat reports/trivy-image-scan-mfr/trivy-report.md reports/trivy-image-scan-unoserver/trivy-report.md > trivy-report.md + + - name: Create or update PR comment + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + set -euo pipefail + comments_endpoint="repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" + comment_id="$({ + gh api --paginate "$comments_endpoint" --jq \ + '.[] | select(.user.login == "github-actions[bot]" and (.body | contains(""))) | .id' + } | sed -n '1p')" + if [[ -n "$comment_id" ]]; then + gh api \ + --method PATCH \ + "repos/${GITHUB_REPOSITORY}/issues/comments/${comment_id}" \ + -F body=@trivy-report.md + else + gh api \ + --method POST \ + "$comments_endpoint" \ + -F body=@trivy-report.md + fi tests: runs-on: ubuntu-latest @@ -52,20 +214,27 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Download Docker image artifact + - name: Download Docker image artifact (build stage) uses: actions/download-artifact@v4 with: - name: rdm-mfr-image + name: rdm-mfr-build-image + path: /tmp + + - name: Download Docker image artifact (unoserver) + uses: actions/download-artifact@v4 + with: + name: rdm-unoserver-image path: /tmp - - name: Load Docker image + - name: Load Docker images run: | - docker load -i /tmp/rdm-mfr-image.tar + docker load -i /tmp/rdm-mfr-build-image.tar + docker load -i /tmp/rdm-unoserver-image.tar - name: Run matrix job env: TEST_BUILD: ${{ matrix.test_build }} - MFR_TEST_IMAGE: ${{ needs.build-image.outputs.image }} + MFR_TEST_IMAGE: ${{ needs.build-image.outputs.build_image }} + MFR_UNOSERVER_IMAGE: ${{ needs.build-image.outputs.unoserver_image }} run: | bash .github/scripts/ci/run-tests.sh "$TEST_BUILD" - diff --git a/.mailmap b/.mailmap index 9acca404b..a5a4c6e1b 100644 --- a/.mailmap +++ b/.mailmap @@ -14,7 +14,6 @@ Eric Bower Erin Braswell erinspace Fitz Elliott Fitz Elliott Haoyu Chen haoyuchen1992 -Jeffrey Spies Jeffrey Spies John Tordoff Johnetordoff Jonathon Love Joshua Carp diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0ead89595..000000000 --- a/.travis.yml +++ /dev/null @@ -1,41 +0,0 @@ -language: python - -python: - - "3.5" - - "3.6" - -sudo: false - -cache: - directories: - - $HOME/wheelhouse - -before_install: - - export WHEELHOUSE=$HOME/wheelhouse - -install: - - travis_retry pip install --upgrade pip - - travis_retry pip install setuptools==37.0.0 - - travis_retry pip install wheel==0.26.0 - - travis_retry pip install invoke==0.13.0 - - travis_retry invoke wheelhouse --develop - - travis_retry invoke install --develop - -env: - - MFR_CONFIG=./travis-config.json - -script: - - invoke test - -before_cache: - # force reinstall for reqs pulled from github repos - - rm -f $HOME/wheelhouse/xlrd-*.whl - - rm -f $HOME/wheelhouse/waterbutler-*.whl - - rm -f $HOME/wheelhouse/aiohttpretty-*.whl - - -notifications: - flowdock: 0221882cdda034c0e9ac2a0e766053dd - -after_success: - coveralls diff --git a/CHANGELOG b/CHANGELOG index f7bb53ed9..6640c9129 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,71 @@ ChangeLog ********* +26.2.1 (2026-10-19) +=================== +- Update rst renderer to fix incorrect invocation. (thanks @Santoshkumarpuppala for the + report and @ihorsokhanexoft for the fix!) + +26.2.0 (2026-10-06) +=================== +- Bump newrelic dep to sync with WaterButler. + +26.1.1 (2026-09-01) +=================== +- Hotfix to add build_spec.yaml for OCI CI/CD. + +26.1.0 (2026-04-28) +=================== +- Rewrite legacy OSF file urls to point to downloadable url. + +26.0.1 (2026-04-06) +=================== +- Bump newerlic dep to work with celery. + +26.0.0 (2026-03-26) +=================== +- Add newerlic support to MFR. (thanks, @antkryt!) +- Fix datetime conversion issue in tabular renderer. (thanks, @antkryt!) +- Fix searching/filterinf in tabular renderer. (thanks, @Vlad0n20!) +- Fix ability to zoom/pan on images. +- Improve error message for unrenderable spreadsheets. + +25.0.0 (2025-11-18) +=================== +- Upgrade MFR and dependencies to python v3.13. +- Allow render jobs to be backgrounded and cached. +- Switch from unoconv to unoserver; upgrade LibreOffice used to convert office files to pdf. +- Switch to pyproject.toml and poetry. + +24.0.0 (2024-01-02) +=================== +- Fix: Install ca-certificates-java in Dockerfile to fix image build. +- Fix: Support newer manifest locations for jamovi files (PR#369). (thanks, @jonathon-love!) +- Fix: Support new manifest type and location for JASP-stats files. (thanks, @JorisGoosen and +@RensDofferhoff!) + +23.1.0 (2023-04-17) +=================== +- Fix: Improve support for special characters in tabular renderer sheet names. (thanks, @aaxelb!) + +23.0.0 (2023-03-30) +=================== +- Docs: Basic repository maintenance for 2023; update copyright dates and update COS jobs url. + +22.0.0 (2022-05-27) +=================== +- Feature: Improve Hypothes.is annotations by allowing the parent frame to pass in its url when +turning on the annotator. +- Feature: Enable syntax highlighting for .boa files (https://boa.cs.iastate.edu/) and bump Pygments +dep to 2.12.0. +- Code: Upgrade MFR's Dockerfile to be based off python3.6 and Debian buster. Remove manual gosu +installation and fetch from apt-get instead. python3.6 is now the only supported python version. +- Code: Migrate CI from TravisCI to Github Actions. + +20.0.1 (2020-10-21) +=================== +- Feature: Add flags to toggle logging of MFR events to specific Keen collections. + 20.0.0 (2020-07-01) =================== - Happy Canada Day, everyone! diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 4f0e8e9e8..50548334c 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -23,8 +23,8 @@ Clone the repo: Configure development environment and install the development dependencies. .. note:: - Python 3.5 or greater, `R`_, and `pspp`_ are required. - Python 3.6 is reccomended. It's recommended that a python version manager such as `pyenv`_ is used and that you use a virtual environment such as `pyenv-virtualenv`_ during development. + Python 3.6 or greater, `R`_, and `pspp`_ are required. + It's recommended that a python version manager such as `pyenv`_ is used and that you use a virtual environment such as `pyenv-virtualenv`_ during development. .. _R: https://www.r-project.org/ .. _pspp: https://www.gnu.org/software/pspp/ diff --git a/Dockerfile b/Dockerfile index 52f40475b..f1ca1bec9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,83 +1,78 @@ -FROM python:3.5-slim-buster - -# ensure unoconv can locate the uno library -ENV PYTHONPATH /usr/lib/python3/dist-packages - -RUN echo "deb https://archive.debian.org/debian buster main" > /etc/apt/sources.list \ - && echo "deb https://archive.debian.org/debian-security buster/updates main" >> /etc/apt/sources.list \ - && 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 \ - # mfr dependencies +# Build stage: compilers and development headers are only needed to install +# the Python dependencies, so they stay out of the runtime image. +FROM python:3.13-slim AS build + +ENV POETRY_HOME=/opt/poetry \ + POETRY_NO_INTERACTION=1 \ + POETRY_VIRTUALENVS_CREATE=0 \ + POETRY_VIRTUALENVS_IN_PROJECT=1 +ENV PATH="${POETRY_HOME}/bin:${PATH}" + +RUN apt-get update \ && apt-get install -y \ + # waterbutler is installed from a git repository git \ - make \ - gcc \ build-essential \ - gfortran \ - r-base \ - libblas-dev \ - libevent-dev \ - libfreetype6-dev \ - libjpeg-dev \ - libpng-dev \ - libtiff5-dev \ - libxml2-dev \ - libxslt1-dev \ - zlib1g-dev \ + libffi-dev \ + libssl-dev \ + && apt-get clean \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* + +# Keep poetry in its own virtualenv so it is not installed into site-packages +RUN python -m venv ${POETRY_HOME} \ + && ${POETRY_HOME}/bin/pip install --no-cache-dir poetry==2.1.2 + +RUN mkdir -p /code +WORKDIR /code + +COPY pyproject.toml poetry.lock /code/ +RUN poetry install --no-root --without=docs + +# Copy the rest of the code over +COPY ./ /code/ + +# Install the project and verify the resolved dependency tree is self-consistent +RUN poetry install --without=docs \ + && python -m pip check + + +# Runtime stage +FROM python:3.13-slim + +RUN usermod -d /home www-data && chown www-data:www-data /home + +RUN apt-get update \ + # pick up Debian security updates published after the base image was built + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ # convert .step to jsc3d-compatible format freecad \ - # pspp dependencies + # convert SPSS .sav to .csv (pspp-convert) pspp \ - # unoconv dependencies - libreoffice \ - # gosu dependencies - curl \ - gnupg2 \ - # gosu - && export GOSU_VERSION='1.10' \ - && mkdir ~/.gnupg && chmod 600 ~/.gnupg && echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf \ - && for server in hkp://ipv4.pool.sks-keyservers.net:80 \ - hkp://ha.pool.sks-keyservers.net:80 \ - hkp://pgp.mit.edu:80 \ - hkp://keyserver.pgp.com:80 \ - ; do \ - gpg --keyserver "$server" --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && break || echo "Trying new server..." \ - ; done \ - && curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ - && curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ - && gpg --verify /usr/local/bin/gosu.asc \ - && rm /usr/local/bin/gosu.asc \ - && chmod +x /usr/local/bin/gosu \ - # /gosu + # grab gosu for easy step-down from root + gosu \ && apt-get clean \ && apt-get autoremove -y \ - curl \ - gnupg2 \ - && rm -rf /var/lib/apt/lists/* \ - && pip install -U pip \ - && pip install setuptools==37.0.0 \ - && mkdir -p /code \ - && pip install unoconv==0.8.2 + && rm -rf /var/lib/apt/lists/* -WORKDIR /code - -COPY ./requirements.txt ./ +COPY --from=build /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages +COPY --from=build /usr/local/bin /usr/local/bin +# nbconvert templates used by the ipynb renderer live outside site-packages +COPY --from=build /usr/local/share/jupyter /usr/local/share/jupyter +COPY --from=build /code /code -RUN pip install --no-cache-dir -r ./requirements.txt +# pip is not needed at runtime and ships its own copies of urllib3, msgpack and +# setuptools, so remove it together with the wheel bundled for ensurepip +RUN python3 -m pip uninstall -y pip \ + && rm -rf /usr/local/lib/python3.13/ensurepip/_bundled \ + && rm -f /usr/local/bin/pip /usr/local/bin/pip3 /usr/local/bin/pip3.13 -# Copy the rest of the code over -COPY ./ ./ +WORKDIR /code ARG GIT_COMMIT= -ENV GIT_COMMIT ${GIT_COMMIT} - -RUN python setup.py develop +ENV GIT_COMMIT=${GIT_COMMIT} EXPOSE 7778 -CMD ["gosu", "www-data", "invoke", "server"] +CMD ["gosu", "www-data", "python3", "-m", "invoke", "server"] diff --git a/Dockerfile.unoserver b/Dockerfile.unoserver new file mode 100644 index 000000000..8902ca559 --- /dev/null +++ b/Dockerfile.unoserver @@ -0,0 +1,50 @@ +# Conversion server for the unoconv extension: LibreOffice driven by unoserver. +# MFR talks to it over XML-RPC (UNOSERVER_EXTENSION_CONFIG_HOST / _PORT), so the +# LibreOffice installation only has to live in this image. +# +# Ubuntu rather than Debian 13: Debian 13 ships LibreOffice against libxml2 2.9.14, whose +# open CVEs cannot be fixed there (the fixed libxml2 2.15 changed ABI and only exists in +# Debian testing), while Ubuntu 26.04 builds LibreOffice against libxml2-16 2.15 with the fixes. +FROM ubuntu:26.04 + +ENV UNOSERVER_HOME=/opt/unoserver + +RUN apt-get update \ + # pick up security updates published after the base image was built + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + # headless LibreOffice modules used by the unoconv exporter formats + libreoffice-writer-nogui \ + libreoffice-calc-nogui \ + libreoffice-impress-nogui \ + libreoffice-draw-nogui \ + # TLS trust store for pip in the venv step below + ca-certificates \ + # Python UNO bridge for the system python used by unoserver + python3-uno \ + python3-venv \ + # fonts: metric-compatible Latin fonts and CJK coverage for Japanese documents + fonts-liberation \ + fonts-dejavu-core \ + fonts-noto-cjk \ + && apt-get clean \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* \ + # the Ubuntu base image ships the pebble service manager (a Go binary outside dpkg); + # nothing here uses it, so drop it rather than carry its Go runtime findings + && rm -f /usr/bin/pebble + +# unoserver has to run under the system python that ships the uno module, so +# the virtualenv is created with access to the system site-packages +RUN python3 -m venv --system-site-packages ${UNOSERVER_HOME} \ + && ${UNOSERVER_HOME}/bin/pip install --no-cache-dir unoserver==3.3.2 \ + && rm -rf ${UNOSERVER_HOME}/lib/python3*/site-packages/pip* + +# LibreOffice needs a writable profile directory for the user it runs as +RUN useradd --create-home --home-dir /home/unoserver --shell /usr/sbin/nologin unoserver +USER unoserver +ENV HOME=/home/unoserver + +EXPOSE 2003 + +CMD ["/opt/unoserver/bin/unoserver", "--interface", "0.0.0.0", "--port", "2003", "--uno-interface", "127.0.0.1", "--uno-port", "2002"] diff --git a/README.md b/README.md index a6a54349d..37795d654 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A Python package for rendering files to HTML via an embeddable iframe. ### Compatibility -MFR is compatible with Python 3.5 (tested up to 3.5.3) and 3.6. +MFR is compatible with Python 3.13. ### Documentation @@ -18,35 +18,32 @@ Documentation available at: http://modular-file-renderer.readthedocs.io/en/lates ### Setting up -Install the latest version of python3.5. +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.5, 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.5` 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 @@ -82,8 +79,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 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 2ae08bb4a..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 -flake8==3.0.4 -ipdb -mccabe -pydevd==0.0.6 -pyflakes -pytest==2.8.2 -pytest-cov==2.2.0 -python-coveralls==2.9.1 -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 d2c435923..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'2018, 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..354de50db 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,16 @@ def __init__(self, message, *args, metadata_url: str='', response: str='', **kwa 'response': self.response }]) + +class UnparseableTableError(RendererError): + + __TYPE = 'unparseable_table' + + def __init__(self, *args, renderer_class: str = '', **kwargs): + super().__init__("File is not loading. Please check its integrity by downloading.", + *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 +163,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 +178,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 +199,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 +211,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..739878039 100644 --- a/mfr/core/extension.py +++ b/mfr/core/extension.py @@ -1,6 +1,14 @@ import abc +import asyncio +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 +50,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 +90,58 @@ 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) + # Poll without blocking the event loop so other requests keep being served while + # the worker renders; give up after ten minutes and let the handler answer 202. + for i in range(100 * 60 * 10): + if not result.ready(): + await asyncio.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 +149,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 696c93a4e..131cd1304 100644 --- a/mfr/core/remote_logging.py +++ b/mfr/core/remote_logging.py @@ -14,7 +14,7 @@ async def log_analytics(request, metrics, is_error=False): """Send events to Keen describing the action that occurred.""" - if settings.KEEN_PRIVATE_PROJECT_ID is None: + if not settings.KEEN_ENABLE_LOGGING or settings.KEEN_PRIVATE_PROJECT_ID is None: return keen_payload = copy.deepcopy(metrics) @@ -78,11 +78,14 @@ async def log_analytics(request, metrics, is_error=False): # send the private payload private_collection = 'mfr_errors' if is_error else 'mfr_action' - 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: + 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 + ): return # build and ship the public file stats payload @@ -98,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() @@ -127,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..841a1715b 100644 --- a/mfr/core/utils.py +++ b/mfr/core/utils.py @@ -1,8 +1,34 @@ -import pkg_resources +from importlib.metadata import entry_points + +import aiohttp from stevedore import driver from mfr.core import exceptions +_client_session = None + + +def get_client_session() -> aiohttp.ClientSession: + """Return the process-wide aiohttp session used to talk to WaterButler and the OSF. + + Creating a session per request leaks the session and its connector (aiohttp logs + "Unclosed client session" for each of them), so a single session is shared. Cookies are + passed explicitly per request and must never be remembered across users, hence the dummy + cookie jar. Must be called from a running event loop. + """ + global _client_session + if _client_session is None or _client_session.closed: + _client_session = aiohttp.ClientSession(cookie_jar=aiohttp.DummyCookieJar()) + return _client_session + + +async def close_client_session(): + """Close the shared session, e.g. on server shutdown.""" + global _client_session + if _client_session is not None and not _client_session.closed: + await _client_session.close() + _client_session = None + def make_provider(name, request, url, action=None): """Returns an instance of :class:`mfr.core.provider.BaseProvider` @@ -10,6 +36,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 +50,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 +60,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 +102,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 +112,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 +120,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 +159,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 +168,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 +181,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 +190,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 ad64fc40b..89dc364dc 100644 --- a/mfr/extensions/codepygments/render.py +++ b/mfr/extensions/codepygments/render.py @@ -1,4 +1,5 @@ import os +import logging import chardet from humanfriendly import format_size @@ -13,6 +14,8 @@ from mfr.extensions.codepygments import settings from mfr.extensions.codepygments import exceptions +logger = logging.getLogger(__name__) + class CodePygmentsRenderer(extension.BaseRenderer): @@ -27,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( @@ -77,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, @@ -86,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, @@ -98,9 +101,12 @@ def _render_html(self, fp, ext, *args, **kwargs): # check if there is a lexer available for more obscure file types if ext in settings.lexer_lib.keys(): lexer = pygments.lexers.get_lexer_by_name(settings.lexer_lib[ext]) + logger.debug('found pygments lexer by name') else: lexer = pygments.lexers.guess_lexer_for_filename(ext, content) + logger.debug('found pygments lexer by guessing') except ClassNotFound: + logger.debug('pygments lexer class not found! using default') self.metrics.add('default_lexer', True) lexer = self.DEFAULT_LEXER() 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..b65d3beae 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'], @@ -34,7 +33,7 @@ def export(self): # and about colors being possibly wrong with warnings.catch_warnings(): warnings.simplefilter("ignore") - image = PSDImage.load(self.source_file_path).as_PIL() + image = PSDImage.open(self.source_file_path).composite() else: image = Image.open(self.source_file_path) @@ -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/image/templates/viewer.mako b/mfr/extensions/image/templates/viewer.mako index f570e9a2e..8962288ff 100644 --- a/mfr/extensions/image/templates/viewer.mako +++ b/mfr/extensions/image/templates/viewer.mako @@ -52,8 +52,7 @@ $(document).ready(function() { - ## Reference on how mobile is detected: https://stackoverflow.com/a/10364620 - var isMobile = window.matchMedia("only screen and (max-width: 760px)"); + var isMobile = window.innerWidth <= 768; ## Enable the zoom feature only for desktop browsers if (!isMobile.matches) { 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 d60733cf6..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), @@ -66,14 +66,20 @@ def _check_file(self, zip_file): """ # Extract manifest file content try: - with zip_file.open('META-INF/MANIFEST.MF') as manifest_data: - manifest = manifest_data.read().decode('utf-8') + try: + # new manifest location + with zip_file.open('meta') as manifest_data: + manifest = manifest_data.read().decode('utf-8') + except KeyError: + # old manifest location + with zip_file.open('META-INF/MANIFEST.MF') as manifest_data: + manifest = manifest_data.read().decode('utf-8') except KeyError: raise jamovi_exceptions.JamoviFileCorruptError( - '{} Missing META-INF/MANIFEST.MF'.format(self.MESSAGE_FILE_CORRUPT), + f'{self.MESSAGE_FILE_CORRUPT} Missing manifest', extension=self.metadata.ext, corruption_type='key_error', - reason='zip missing ./META-INF/MANIFEST.MF', + reason='zip missing manifest', ) lines = manifest.split('\n') @@ -87,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.', @@ -98,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 ffcc8a76d..ae2b2bf8f 100644 --- a/mfr/extensions/jasp/render.py +++ b/mfr/extensions/jasp/render.py @@ -1,3 +1,4 @@ +import json import os from mako.lookup import TemplateLookup @@ -20,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) @@ -28,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), @@ -49,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', @@ -67,16 +68,30 @@ def _check_file(self, zip_file): """ # Extract manifest file content try: - with zip_file.open('META-INF/MANIFEST.MF') as manifest_data: - manifest = manifest_data.read().decode('utf-8') + try: + # new manifest location + with zip_file.open('manifest.json') as manifest_data: + manifest, flavor = manifest_data.read().decode('utf-8'), 'json' + except KeyError: + # old manifest location + with zip_file.open('META-INF/MANIFEST.MF') as manifest_data: + manifest, flavor = manifest_data.read().decode('utf-8'), 'java' except KeyError: raise exceptions.JaspFileCorruptError( - '{} Missing META-INF/MANIFEST.MF'.format(self.MESSAGE_FILE_CORRUPT), + f'{self.MESSAGE_FILE_CORRUPT} Missing manifest', extension=self.metadata.ext, corruption_type='key_error', - reason='zip missing ./META-INF/MANIFEST.MF', + reason='zip missing manifest', ) + if flavor == 'java': + self._verify_java_manifest(manifest) + else: + self._verify_json_manifest(manifest) + + return True + + def _verify_java_manifest(self, manifest): lines = manifest.split('\n') # Search for Data-Archive-Version @@ -92,7 +107,7 @@ def _check_file(self, zip_file): 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.', @@ -115,10 +130,47 @@ def _check_file(self, zip_file): ) 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 True + return + + def _verify_json_manifest(self, manifest): + + manifest_data = json.loads(manifest) + + jasp_archive_version_str = manifest_data.get('jaspArchiveVersion', None) + if not jasp_archive_version_str: + raise exceptions.JaspFileCorruptError( + f'{self.MESSAGE_FILE_CORRUPT} jaspArchiveVersion not found.', + extension=self.metadata.ext, + corruption_type='manifest_parse_error', + reason='jaspArchiveVersion not found.', + ) + + # Check that the file is new enough (contains preview content) + jasp_archive_version = LooseVersion(jasp_archive_version_str) + try: + if jasp_archive_version < self.MINIMUM_VERSION: + minimum_version = self.MINIMUM_VERSION.vstring + data_archive_version = jasp_archive_version.vstring + raise exceptions.JaspVersionError( + 'This JASP file was created with an older data archive ' + 'version ({}) and cannot be previewed. Minimum data archive ' + 'version is {}.'.format(data_archive_version, minimum_version), + extension=self.metadata.ext, + actual_version=data_archive_version, + required_version=minimum_version, + ) + except TypeError: + raise exceptions.JaspFileCorruptError( + f'{self.MESSAGE_FILE_CORRUPT} jaspArchiveVersion not parsable.', + extension=self.metadata.ext, + corruption_type='manifest_parse_error', + 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..fe9851c18 100644 --- a/mfr/extensions/rst/render.py +++ b/mfr/extensions/rst/render.py @@ -19,9 +19,9 @@ 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: - body = publish_parts(fp.read(), writer_name='html')['html_body'] + def _render(self): + with open(self.file_path) as fp: + body = publish_parts(fp.read(), writer_name='html', settings_overrides={'file_insertion_enabled': False, 'raw_enabled': False})['html_body'] return self.TEMPLATE.render(base=self.assets_url, body=body) @property 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 0cdb4f613..b41961d06 100644 --- a/mfr/extensions/tabular/templates/viewer.mako +++ b/mfr/extensions/tabular/templates/viewer.mako @@ -4,10 +4,11 @@
+
@@ -30,28 +31,44 @@ 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]; - sheetName = sheetName.replace( /(:|\.|\[|\]|,|@|&|\ )/g, '_' ); //Handle characters that can't be in DOM ID's - $("#tabular-tabs").append('
  • '+ sheetName + '
  • '); - gridArr[sheetName] = [sheet[0], sheet[1]]; + // Handle characters that can't be in DOM ID's + var sheetCoded = window.btoa(encodeURIComponent(sheetName)).replace(/=/g, ''); + $("#tabular-tabs").append('
  • '+ sheetName + '
  • '); + gridArr[sheetCoded] = [sheet[0], sheet[1]]; - $('#'+sheetName).click(function (e) { + $('#'+sheetCoded).click(function (e) { e.preventDefault(); var columns = gridArr[$(this).attr('id')][0]; var rows = gridArr[$(this).attr('id')][1]; 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 @@ -74,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, map(_convert_value, 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 UnparseableTableError + + 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 UnparseableTableError + + 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..5b4e72ad8 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,8 @@ def file_required(self): @property def cache_result(self): return self.renderer.cache_result + + @property + def use_celery(self) -> bool: + # Office documents are always rendered through a Celery worker, as upstream does. + 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..90f93b9a3 100644 --- a/mfr/providers/http/provider.py +++ b/mfr/providers/http/provider.py @@ -4,12 +4,12 @@ import mimetypes from urllib.parse import urlparse -import aiohttp from waterbutler.core import streams from mfr.core import provider from mfr.core import exceptions +from mfr.core import utils logger = logging.getLogger(__name__) @@ -29,14 +29,16 @@ 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) + # The response is kept open on purpose, the returned stream reads from it. + response = await utils.get_client_session().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'))) + err_resp = await response.text() + await response.release() + logger.error(f'Unable to download file: ({response.status}) {err_resp}') raise exceptions.DownloadError( 'Unable to download the requested file, please try again later.', download_url=self.url, - response=await response.text(), + response=err_resp, code=response.status, provider='http', ) diff --git a/mfr/providers/osf/provider.py b/mfr/providers/osf/provider.py index 4745e8ecc..cac4ad8a3 100644 --- a/mfr/providers/osf/provider.py +++ b/mfr/providers/osf/provider.py @@ -1,4 +1,5 @@ import os +import re import json import hashlib import logging @@ -6,12 +7,11 @@ import mimetypes import furl -import aiohttp -from aiohttp.errors import ContentEncodingError from waterbutler.core import streams from mfr.core import exceptions +from mfr.core import utils from mfr.core import provider from mfr.core.utils import sizeof_fmt from mfr.providers.osf import settings @@ -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, @@ -149,9 +152,13 @@ async def download(self): self.metrics.add('download.saw_redirect', False) if response.status in (302, 301): + location = response.headers['location'] await response.release() - response = await aiohttp.request('GET', response.headers['location']) self.metrics.add('download.saw_redirect', True) + # Follow the redirect ourselves without the OSF credentials: the target is usually a + # signed storage URL that must receive neither the cookie nor the Authorization header. + # The response is kept open on purpose, the returned stream reads from it. + response = await utils.get_client_session().get(location) return streams.ResponseStreamReader(response) @@ -168,11 +175,23 @@ async def _fetch_download_url(self): self.download_url = self.url self.metrics.add('download_url.orig_type', 'wb_v1') else: - self.metrics.add('download_url.orig_type', 'osf') + normalized_url = None + if re.compile(r'^/[a-z0-9]{5}/[^/]*', re.IGNORECASE).match(path): + # In the past the OSF would redirect urls of the form https://osf.io// to + # https://osf.io/download//. It no longer does this, so MFR must detect + # such urls and manually prepend /download/ to the path. + self.metrics.add('download_url.orig_type', 'osf-preangular') + temp_url = furl.furl(self.url) + temp_url.path.segments = ['download'] + temp_url.path.segments + normalized_url = temp_url.url + else: + self.metrics.add('download_url.orig_type', 'osf') + normalized_url = self.url + # make request to osf, don't follow, store waterbutler download url request = await self._make_request( 'GET', - self.url, + normalized_url, allow_redirects=False, headers={ 'Content-Type': 'application/json' @@ -180,11 +199,11 @@ 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, - metadata_url=self.url, + metadata_url=normalized_url, provider=self.NAME, code=request.status, ) @@ -205,4 +224,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 utils.get_client_session().request(method, url, *args, **kwargs) diff --git a/mfr/server/app.py b/mfr/server/app.py index d7f4b2abc..4da7c5906 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 @@ -18,25 +21,40 @@ from mfr.server.handlers.renderers import RenderersHandler from mfr.server.handlers.core import ExtensionsStaticFileHandler from mfr.version import __version__ +from mfr.core import utils logger = logging.getLogger(__name__) access_logger = logging.getLogger('tornado.access') 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.add_callback(close_and_stop) + + async def close_and_stop(): + await utils.close_client_session() + 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 +64,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,10 +86,24 @@ def make_app(debug): debug=debug, log_function=almost_apache_style_log, ) - app.sentry_client = AsyncSentryClient(settings.SENTRY_DSN, release=__version__) return app +def http_server_options(): + """Options for tornado's HTTPServer. + + Besides the read buffer size, cap the request body and header sizes. MFR handlers only + answer GET, but tornado parses multipart and URL-encoded bodies before the handler's + method is checked, so without a cap a crafted body of up to the buffer size is parsed. + """ + return { + 'xheaders': server_settings.XHEADERS, + 'max_buffer_size': server_settings.MAX_BUFFER_SIZE, + 'max_body_size': server_settings.MAX_BODY_SIZE, + 'max_header_size': server_settings.MAX_HEADER_SIZE, + } + + def serve(): tornado.platform.asyncio.AsyncIOMainLoop().install() @@ -78,12 +119,11 @@ def serve(): app.listen( server_settings.PORT, address=server_settings.ADDRESS, - xheaders=server_settings.XHEADERS, - max_buffer_size=server_settings.MAX_BUFFER_SIZE, ssl_options=ssl_options, + **http_server_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/server/settings.py b/mfr/server/settings.py index 7be65b8b1..32ff6afa4 100644 --- a/mfr/server/settings.py +++ b/mfr/server/settings.py @@ -22,6 +22,11 @@ CHUNK_SIZE = int(config.get('CHUNK_SIZE', 65536)) # 64KB MAX_BUFFER_SIZE = int(config.get('MAX_BUFFER_SIZE', 1024 * 1024 * 100)) # 100MB +# MFR answers GET requests only and never reads a request body, but tornado parses form +# bodies (multipart, URL-encoded) before the handler's method is checked, so cap what a +# request may carry instead of letting it fill the 100MB buffer. +MAX_BODY_SIZE = int(config.get('MAX_BODY_SIZE', 64 * 1024)) # 64KB +MAX_HEADER_SIZE = int(config.get('MAX_HEADER_SIZE', 32 * 1024)) # 32KB PROVIDER_NAME = config.get('PROVIDER_NAME', 'osf') @@ -43,11 +48,15 @@ keen_config = analytics_config.child('KEEN') KEEN_API_BASE_URL = keen_config.get('API_BASE_URL', 'https://api.keen.io') KEEN_API_VERSION = keen_config.get('API_VERSION', '3.0') +KEEN_ENABLE_LOGGING = keen_config.get_bool('ENABLE_LOGGING', True) keen_private_config = keen_config.child('PRIVATE') KEEN_PRIVATE_PROJECT_ID = keen_private_config.get_nullable('PROJECT_ID', None) KEEN_PRIVATE_WRITE_KEY = keen_private_config.get_nullable('WRITE_KEY', None) +KEEN_PRIVATE_LOG_VIEWS = keen_private_config.get_bool('LOG_VIEWS', True) +KEEN_PRIVATE_LOG_ERRORS = keen_private_config.get_bool('LOG_ERRORS', True) keen_public_config = keen_config.child('PUBLIC') KEEN_PUBLIC_PROJECT_ID = keen_public_config.get_nullable('PROJECT_ID', None) KEEN_PUBLIC_WRITE_KEY = keen_public_config.get_nullable('WRITE_KEY', None) +KEEN_PUBLIC_LOG_VIEWS = keen_public_config.get_bool('LOG_VIEWS', True) diff --git a/mfr/server/static/js/mfr.child.hypothesis.js b/mfr/server/static/js/mfr.child.hypothesis.js index ba8416d9a..c3eb71067 100644 --- a/mfr/server/static/js/mfr.child.hypothesis.js +++ b/mfr/server/static/js/mfr.child.hypothesis.js @@ -2,15 +2,23 @@ 'use strict'; var hypothesisLoaded = false; + var parentWindowUrl = undefined; + + window.pymChild.onMessage('setParentUrl', setParentWindowUrl); window.pymChild.onMessage('startHypothesis', startHypothesis); window.addEventListener('message', function(event) { - if (event.data === 'startHypothesis') { + if (event.data.type === 'startHypothesis') { + setParentWindowUrl(event.data.parentUrl); startHypothesis(event); } }); + function setParentWindowUrl(parentUrl) { + parentWindowUrl = parentUrl; + } + function startHypothesis(event) { if (hypothesisLoaded) { return; @@ -53,7 +61,7 @@ // point to the export/download url, meaning the annotations could never be viewed in // context. By linking to the referrer, the annotations can be viewed in the context of // the preprint. - window.PDFViewerApplication.url = document.referrer; + window.PDFViewerApplication.url = parentWindowUrl; // Load the hypothes.is client var script = window.document.createElement('script'); diff --git a/mfr/server/static/js/mfr.js b/mfr/server/static/js/mfr.js index 4fff36715..57c30f005 100644 --- a/mfr/server/static/js/mfr.js +++ b/mfr/server/static/js/mfr.js @@ -112,6 +112,7 @@ }; self.startHypothesis = function() { + self.pymParent.sendMessage('setParentUrl', window.location.toString()); self.pymParent.sendMessage('startHypothesis'); }; 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..223dada29 --- /dev/null +++ b/mfr/tasks/settings.py @@ -0,0 +1,51 @@ +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) +# One result queue per task, as the amqp backend of Celery 4 did. The rpc backend collects +# the results of a client in one queue and polls it with basic_get; a result left there by an +# earlier task is fetched as an out-of-band message and never acknowledged, so RabbitMQ closes +# the channel after its consumer timeout and the next task call fails. +DEFAULT_RESULT_BACKEND = 'celery_amqp_backend.AMQPBackend://' +result_backend = config.get_nullable('CELERY_RESULT_BACKEND', DEFAULT_RESULT_BACKEND) +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 + +# Workers exchange remote control messages (including the hello/reply done at startup) on a +# broadcast exchange shared by every Celery application on the broker. Other applications on +# the same broker may serialize those messages with pickle, which this JSON-only worker rejects, +# so keep MFR's control traffic on an exchange of its own. +control_exchange = config.get('CELERY_CONTROL_EXCHANGE', 'mfr') + +imports = [ + "mfr.tasks.export", + "mfr.tasks.render", +] diff --git a/mfr/version.py b/mfr/version.py index 2ddc72372..b56d4ca3b 100644 --- a/mfr/version.py +++ b/mfr/version.py @@ -1 +1 @@ -__version__ = '20.0.0' +__version__ = '26.2.1' diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 000000000..aeba64a2c --- /dev/null +++ b/poetry.lock @@ -0,0 +1,4644 @@ +# This file is automatically @generated by Poetry 2.1.2 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 = "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 = "asttokens" +version = "3.0.2" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "asttokens-3.0.2-py3-none-any.whl", hash = "sha256:9da13157f5b28becde0bd374fc677dcd3c290614264eff096f167c469cd9f933"}, + {file = "asttokens-3.0.2.tar.gz", hash = "sha256:3ecdbd8f2cc195f53ccada3a613538bb5f9ef6f6869129f13e03c30a677b8fe2"}, +] + +[package.extras] +astroid = ["astroid (>=2,<5)"] +test = ["astroid (>=2,<5)", "pytest (<9.0)", "pytest-cov", "pytest-xdist"] + +[[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 = "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 = ["dev"] +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.4.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "bleach-6.4.0-py3-none-any.whl", hash = "sha256:4b6b6a54fff2e69a3dde9d21cc6301220bee3c3cb792187d11403fd795031081"}, + {file = "bleach-6.4.0.tar.gz", hash = "sha256:4202482733d85cedd04e59fcb2f89f4e4c7c385a78d3c3c23c30446843a37452"}, +] + +[package.dependencies] +tinycss2 = {version = ">=1.1.0", optional = true, markers = "extra == \"css\""} +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0)"] + +[[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", "dev", "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\" or platform_system == \"Windows\""} + +[[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 = ["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 = ["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 = "executing" +version = "2.3.0" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "executing-2.3.0-py3-none-any.whl", hash = "sha256:736e859c9f8701f11fcf516856f26f562e04776387824b43a35a1dfe21c84122"}, + {file = "executing-2.3.0.tar.gz", hash = "sha256:15919cb5d667e5cb4e099511971d00d659573fff2dd5c4e6cd8b71636c7858d2"}, +] + +[package.extras] +tests = ["asttokens (>=2.1.0)", "coverage-enable-subprocess", "coverage[toml]", "ipython", "littleutils", "pysource-minimize (>=0.10.1)", "pytest", "rich ; python_version >= \"3.11\""] + +[[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.20" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.9" +groups = ["main", "dev", "docs"] +files = [ + {file = "idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c"}, + {file = "idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44"}, +] + +[package.extras] +all = ["coverage (>=7.10.0)", "hypothesis (>=6.141.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.16.0)", "ty (>=0.0.37)"] + +[[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 = "9.17.1" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.11" +groups = ["main", "dev"] +files = [ + {file = "ipython-9.17.1-py3-none-any.whl", hash = "sha256:6d1645743cfd1a07eb695d85aa2b5fa66721f8cbae9431d4049f7084bbf06509"}, + {file = "ipython-9.17.1.tar.gz", hash = "sha256:8919be8c27f20a6f4423145028063f6637b42a03ce57665bb12015ee1f073529"}, +] + +[package.dependencies] +colorama = {version = ">=0.4.4", markers = "sys_platform == \"win32\""} +ipython-pygments-lexers = ">=1.0.0" +jedi = ">=0.18.2" +matplotlib-inline = ">=0.1.6" +pexpect = {version = ">4.6", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt_toolkit = ">=3.0.41,<3.1.0" +psutil = {version = ">=7", markers = "sys_platform != \"emscripten\" and sys_platform != \"cygwin\""} +pygments = ">=2.14.0" +stack_data = ">=0.6.0" +traitlets = ">=5.13.0" + +[package.extras] +all = ["argcomplete (>=3.0)", "ipython[doc,matplotlib,test,test-extra]"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[matplotlib,test]", "setuptools (>=80.0)", "sphinx (>=8.0)", "sphinx-rtd-theme (>=0.1.8)", "sphinx_toml (==0.0.4)", "typing_extensions"] +matplotlib = ["matplotlib (>3.9)"] +test = ["packaging (>=23.0.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=1.0.0)", "setuptools (>=80.0)", "testpath (>=0.2)"] +test-extra = ["curio", "ipykernel (>6.30)", "ipython[matplotlib]", "ipython[test]", "jupyter_ai", "nbclient", "nbformat", "numpy (>=2.0)", "pandas (>2.1)", "trio (>=0.22.0)"] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +description = "Defines a variety of Pygments lexers for highlighting IPython code." +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c"}, + {file = "ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81"}, +] + +[package.dependencies] +pygments = "*" + +[[package]] +name = "isort" +version = "6.1.0" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.9.0" +groups = ["dev"] +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.6" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +groups = ["main", "docs"] +files = [ + {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, + {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, +] + +[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 = "mako" +version = "1.4.3" +description = "A super-fast templating language that borrows the best ideas from the existing templating languages." +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "mako-1.4.3-py3-none-any.whl", hash = "sha256:723296007c870bfd6b3f0c3230dba7198096e5269297ebf5e4eff9e7ffa39d4f"}, + {file = "mako-1.4.3.tar.gz", hash = "sha256:cd6537fe88d5fec315c55c2f8529bc4ce7a9a352ad7db3eeaa6a66e2dd4ec37a"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +babel = ["Babel"] +lingua = ["lingua (>=4.16)"] +testing = ["pytest"] + +[[package]] +name = "markdown" +version = "3.11" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.11" +groups = ["main"] +files = [ + {file = "markdown-3.11-py3-none-any.whl", hash = "sha256:cd6c89e7eb308c8b332ed673215a52d208a43f8bacc030b1419376129408719e"}, + {file = "markdown-3.11.tar.gz", hash = "sha256:180224db6aed87ba9ce1f2781ebcd5826253de8ff637112090e24b84502bbf9f"}, +] + +[package.extras] +docs = ["ghp-import (==2.1.0)", "justhtml (==3.11.2)", "mdx_gh_links (==0.4)", "mkdocstrings (==1.0.6)", "mkdocstrings-python (==1.16.8)", "pygments (==2.21.0)", "pymdown-extensions (==11.0.2)", "zensical (==0.0.62)"] +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.3.4" +description = "A sane and fast Markdown parser with useful plugins and renderers" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "mistune-3.3.4-py3-none-any.whl", hash = "sha256:ee015381e955e370962968befe1d729ab60fafb6a715ac6751763fbce38c8d4a"}, + {file = "mistune-3.3.4.tar.gz", hash = "sha256:58b5c96d6fcb61190dfe5fae498d2b2065f99cf61e9649418fd54cf1ada86dfe"}, +] + +[[package]] +name = "multidict" +version = "6.9.1" +description = "multidict implementation" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "multidict-6.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aef74e9beabbd6c4aafc091dabff86d046ccf013ce1e4396c0fbb01b4cad9de8"}, + {file = "multidict-6.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1ca5ebe6d454f1e5496cf052386a559f1080bf2de75bf327ebca0a6003b79f19"}, + {file = "multidict-6.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f6d0c4b70f783305e73f9944d8efe6be1022550f0974ba0ae9d8893c0350fa"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8050e75af7e4c6e2d5260b84eeedb618f3e452e66473432e085b5d1b81429299"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4736d350371337825cac1793c9f7c40701c32a03912548c2a7608e51679cbb96"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:02fe09dc197b8ae7e355371e51e5dce2f39060cd5a8badf94904527e23a3f188"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ad4528cdce058b684f75fad1faf4a6a6c992fe2f08376370ca66e4ce5916a84a"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8885e3808aedbd6725b921fb67dacaae0678933561ddd47c2b01315198c70e2e"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3b6e6840421c83ccb60398e333b44f910b0907bb409597685ab2eedd1e22eab"}, + {file = "multidict-6.9.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c9648ed33dc8179e4ec04bbc73bd7f0038e1e81217a69467f61f02a78bf07e88"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d9d6544790ba50438a9c1a903c3c4afb1ec8a7832db5518549275b40ef0dd4b1"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1c9f3c25df6c9d3bbae4f6fd3f514b1c5c740a2110f56ccf36069c85417e289c"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cf22b43f35b7dbb9f71e8ee2041b5c00029cdfc28ede3a2f31cf8906f9a6c126"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8ed78ccad4c7b421804f5d524b7740946a7ef75d89dc0dac52e9d7c24c472410"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:e3b1aa25f01238886a6baed9e13b9a9240ed344346c79ae280ae65e8603b21d5"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bc94a68ea5e18f8e85dc6b522bcb53093f692c8eb62b4837ac047da73956cbe4"}, + {file = "multidict-6.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73533644e1f69ea1164d56cc6505f564c6c44072b646b66d67df2d31fed0348c"}, + {file = "multidict-6.9.1-cp310-cp310-win32.whl", hash = "sha256:66987aa68b0f7c2a1cc5f388ca962b8ed92b10f79de38d6d0d8c716154f519d9"}, + {file = "multidict-6.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:a32b78c1e52ebd8e247bb68300b90b233300d8816faa008ed0713bc539fb6af0"}, + {file = "multidict-6.9.1-cp310-cp310-win_arm64.whl", hash = "sha256:ab64ace1a68682d191d9bedd9d4c939406ad86b1d9f628180410644249ad46c2"}, + {file = "multidict-6.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:910d4260512660484c0dc1588a316fbb35a40c081c36fc51d1225351af17cfe4"}, + {file = "multidict-6.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:33fa55b990f81c2927e01399ace0d18926c69d69baa8cdaa819424132fb97987"}, + {file = "multidict-6.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:369b5aa01b241cd3fea6890bdbb11a1425d87bf1515831500d518f4223e9d72c"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:803f8b575a71b1b299d677c28db0653459c79b5308874efec813f17b7457c7f1"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8a65621b98984a62e59403009591b8a5a7736273aefe1cab64cfb85b365cc07"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:13849a1d4f54c3809ae721e9e83ab28f5ea602f33660cb84eb6ef261eac706c1"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dd9a137a4a9becda3094f3831cd026380f75f6855e051eefe4c73ade524f1cc3"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9ae9614c317c50836689ce2dfde07c05fe0b16378562e2221746c3913ede3c80"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8f1e362c9352b50ed120f001046fdbb80810c9d56580f4c3fc13bbe30823387"}, + {file = "multidict-6.9.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0dd655518f136febd96c05131a76a863e32fc2a1d7acd4e3c959e3ceb77d8345"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c5d675da8f1cb5650271c8ad5e95c0a3e5a183c105e72d953b12877b1c8d0fd"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:658f90f49cf5af2441cad0a2b801c3ef520471989a1ec55bcb25b255b2ca8d2f"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:43124fe172ada86d03ac3c8dc8179091341f6724d5e5d5b160e1587e4cd3761b"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f0adc22a4eb31e545221d93fc73a0f6a8cc2379d0f4309f71d1d17ba938b82"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7fc59e9ba821b220944ccfe0f89c9dc4745f6d097569992356eb03869f21e953"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:87cc632c88ee5dc80e12681047839304d98ee5c9a708d686505767001c9b8b9a"}, + {file = "multidict-6.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b828cf64d62dc09ac183f03c1aeedd164ade96a2ce4934109452edf29de1dd13"}, + {file = "multidict-6.9.1-cp311-cp311-win32.whl", hash = "sha256:2c1aeb92eea59d824f004341b26d5e4b47a8a441cf9726769b9a90abf9d0e08f"}, + {file = "multidict-6.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:5f89dad732280e7a10b74d40b91364f88e13c3f2c08c2ef83a8cd42f7a61af2e"}, + {file = "multidict-6.9.1-cp311-cp311-win_arm64.whl", hash = "sha256:5800368526647146978389dfaa46da3356291e9f0fff9a4ef12e8c2bef964a0d"}, + {file = "multidict-6.9.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:29138fef49828542e859828107e42e50d0e587c513b7eb4b2d92bade2b0860fe"}, + {file = "multidict-6.9.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:19e31815d41cefc365489e591d105d2baceb2f65aa75d29471fbdbda8651e006"}, + {file = "multidict-6.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6ed30be8918e18c8bed0a2e8b70639ecf02feb61ed00ca2e41cfcb2a50fa3f42"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:637f4ae36264bd7b8d9a60193acddc1d735ad52e8ed53a19931ea6d921fea8e5"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35fc236507fb1b3138f0af5ecd5f94ed752d4d6d826248eae425f86204013eea"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e58952f04772f59f11c6e007471449809a30165188669bca8fdb19dde40a8f24"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d35a4f1c63f07fbb8c8f9946dea98b21eddf6c57421585f71d91864be3ba2a24"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b5f8771aaaed7f80e84a4e471d2f29ab6721e4595075e54d03ae1ed951b2000a"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:976fd7689d69ec78d67d31d38d396d8adb562f7e8368279f76aed4aa451fa06d"}, + {file = "multidict-6.9.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:95052e8777a86bae87c0bd0b5ab22d809e3d1d02bf69e3e66ddda5ba75a05805"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1a8adfcaf96f587ab138476eaddef95f29b8a2a8a9afbfea8d2fd62180995d02"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1a53de2772cfb74559df2eb4456ec4eeb908435ec55a84b69370d9d745d62aa8"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f2ce963299d42fa3f22a90adc0fdf174792ffef5ff4c7ffb68260548fb05580"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5b30ddf7234e611ca877575b62840e6af5977f92f1f9d532eedbb05a44ff8004"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:63ada7ee2e9345695f9e9bc4c65d72222253f07b1ac94fd0e37555cc6f3c7f60"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3c95601ed98fad3f6e2f8fe809c3b526b0fab31ef525e00a155e227f3d17f58a"}, + {file = "multidict-6.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c148e8b596000dd3e4bfe206e70f3e666be18d72032e0012555f2373c52e35d6"}, + {file = "multidict-6.9.1-cp312-cp312-win32.whl", hash = "sha256:f9dad513626a33670f17cddc6078e30e311f444c957e8dbfc5b2b4603c8b4edb"}, + {file = "multidict-6.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:a16a1dc8529f9e734a41c3b856f3eae7ebacdc061dde3f8a844e0c7889c97203"}, + {file = "multidict-6.9.1-cp312-cp312-win_arm64.whl", hash = "sha256:361f7206cf341ba94fb015688f5c8b480f8e63bd58a4c14a48aeca7851a241cc"}, + {file = "multidict-6.9.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:d7bf9e43282d69561618e8a0ea33368d532ebef42f15c096f427090521dd74f3"}, + {file = "multidict-6.9.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:03d47df72f084f757c1cb771188d5f4e3a805e4abc4d67e32509272343ae9382"}, + {file = "multidict-6.9.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6bc94fe17c3c56e5418f79515b786b101845f70609b0d19d0c1ba13448e5633a"}, + {file = "multidict-6.9.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8f2973bbd2bebd9d2e0cd6394c1292a1a19ccd56bdcbe1e174059f1a39be5b40"}, + {file = "multidict-6.9.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de7738b8c0bb74c4cc16bbd7fb49fc2bcf6430dba11b3432cd52768ae40933e8"}, + {file = "multidict-6.9.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e5ccad4b7bac125722f48d6f862bed3b514d8526deea06316bb72f152cd30a7c"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a49ff5cdb33654cb7d6a3c377aa2a83ddefaa1db31eb10bcf3c180aa84f9af8a"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b22ff30006a2f28f8bff878fb93413cbe3a4d1fd517c28081d848c90e9cfd2c8"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3adf06c66041aa21eeb8a71e82379b74773298c8e6d3d839b151aae441a99b94"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:963a8d8f97057082679523d0fd4c53a38f86bc58cabe4556faef682ae53fa2fa"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b66ccc5c2cdd26e74fa5d4c29ffae424cc6148bf93ce574821783fb3b6d452c5"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7fd79c521f6290c69125fa2b85fa65d9e657e6a8ffaf722dc881b926bef4aa5c"}, + {file = "multidict-6.9.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d804e4caf5d5da37d6dac1325da5629ebef1e27a294c2b568b295814aa36c7b"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bb0d664505f4b112f384cffeee82e91e3f6448d8e574989479db4439b68cba05"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9e14d17773b1b3c758ff153659a1824608a0cb562c45f484b5ed8a433428444a"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:083735b7f395894e43adb278d5dae901448883a835ff8f1977e285fefdb10418"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b65121091567847a8cb520d364ab22ba90e00d3cc55fa9eb34bb439f0684bcd1"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ea999ae6e80e66ad5eea287860951b033d0104ca34d6d87c7b5125ebe0e12721"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:095d900c242e00fbe5f321ee072e7278b4153e78c5ce9c1efde167d62c1e4771"}, + {file = "multidict-6.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6441cc837aea58be7d9baef1b2383eb8311ab9303f500f99ac90b584cd78bb14"}, + {file = "multidict-6.9.1-cp313-cp313-win32.whl", hash = "sha256:9c4880d017555d70dea367dd49271830842d48e3891c2da97da7ce8c4abcee40"}, + {file = "multidict-6.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:ac51cd64bae51c462ea58ad2492c9b8209667a4ef60c45c4a304518b67598d5d"}, + {file = "multidict-6.9.1-cp313-cp313-win_arm64.whl", hash = "sha256:37a9ebe00c698279213d56e6c64e1962ab1e092918270649b397cac3dc196ca4"}, + {file = "multidict-6.9.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:fc0dcb22fa9aeabfe3fa4e0430099acff985ec5d77a851382f76cc6146e780e5"}, + {file = "multidict-6.9.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:024123f0ab402ab33828e24eb80fa8f25167d0d3783ba5f287e39ed741e6abf9"}, + {file = "multidict-6.9.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:af1b5a92315048c3e36bbebfa7d4760a9c3e910bc4166f11b20d77d20d6bcfca"}, + {file = "multidict-6.9.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:b2483da477932ad1983d1d33c18bc3771c6fb00cfbaaed70a875fd547ef8e840"}, + {file = "multidict-6.9.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:db4d697b18b6ef5528b1f36bfa25072cd2a421869f5963bc0e92c8a34b9e2800"}, + {file = "multidict-6.9.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:854fd2f1bc6e8a56b89910b5cd7261a8b40f13ebb31572da985ce59c7da0886d"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:03731f6fc036180700c9dc2308205a48e5ca6f3ff03087739ab746f294022201"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:989261c5f1735a165f2e4e87cf6d5f17ab734fa18f9ad0383d5adfcdaefce701"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b4c9e5d05b126b267ac048a89a0e2d9b48b1b648add62d4872906304a8590610"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9d0a21cf76153de8f2d96a877991d6bc59b9ab5180b949e50db73cc193b4a694"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7386aa18d98d6b8af44b92173654ec469237fda35f8e8523e43b581a86f476a"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b69651732c64afb691e50cdc3387cae305e0eeff8804fe3e3ce203876494932a"}, + {file = "multidict-6.9.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1fee9a16d88a1c4865610de31ef5c666671020d7a81d1f510eaf3c97d00ebeba"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7814bbee202acd3bd240204c17d8b87a4c48c81064fd8674dbe527d94d5a4290"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:95f273bea318a194f656527ee2ed19494327bc500b8e87d9358e3222579aa28d"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:73bcafa21a78d0776b3ee7cd2a63c66f968eb7db8e8d594e32d7329950f6e828"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1a938761c77e0e6edb0c93d02f4e988d44a69e5195e5a3b893e5553311347132"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:37245ca4105386194dd1d292a6f2aae09bfe1bd7ac6f9ec25093e3cf8e9b143b"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f0700527dd5bfa8b7204b08330542f4f388899d3c14d885d8a368992e0eb562d"}, + {file = "multidict-6.9.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6b7e54fd883671d1a8810704851c044b7173287c552b9f5c3d9e0eb9f00ae194"}, + {file = "multidict-6.9.1-cp314-cp314-win32.whl", hash = "sha256:e81ae656b9935ac4528a71f96bb7a14d949778ed1897c573d3e7ebb9187f8841"}, + {file = "multidict-6.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:acddcac38adc8342ba48aba98896faa7928854bebb62542362138655b5367ee3"}, + {file = "multidict-6.9.1-cp314-cp314-win_arm64.whl", hash = "sha256:32217133dddc58c927805cf6c0731d8144584176b768042ee886d51e71860bc9"}, + {file = "multidict-6.9.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0b2fb8c349d1103863750b5d8cb5ace766917f4b35f3d883c8f778853eaa9f76"}, + {file = "multidict-6.9.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:56d834b74c993a7d7cb2b8ab33a0d55c3e0d4a3d2f2da2808a4ad3d79189711b"}, + {file = "multidict-6.9.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:783ba7d845d79ce976afd9c1e91a4e5714671defa198ee789e8b23316083a485"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d718fa1b5f0d0dd75e86fbbc5b0c93ea3a5d65216c85c61cd5d7cdddfe08455"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a313bad717dde740959d50850c315b75fd4eb0c5e6b4dc8535db0f1c369be125"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ef01d29fca550ab871fd99154f82c6472aacf8e7def272dfb07b460123850390"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f3bd290711c6e9486173a6ee7cd4e7f00c3971c7908c1ec1b6e5437c5e4c6f9"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:81cdc537e0a42e3c0170752fcadbe450246d5c3b4b7231d6eb9672456605ac94"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8b193bf7a443c97d81c47052f60c486071a4bdef4a573fa2514f920089414d45"}, + {file = "multidict-6.9.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7a0c98f6a636adf0d7edd60c61589eaf52d149239af754d0bfeb0effedba53a8"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6e6b7e3a1520c39a2772f414cd9ddf5995f77e4e823dfa1522af383addd465a3"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:ca65cced0d67a9039e93bcd98a369920e499bf98296844ff56ead01c9085321f"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:372c063f37480f62c1ae32dc3a1a0a5942b180c883f99789075a8a8ec3c4e709"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:827c92145b3b976b39430129c89d213b250dacbe5fce678e9a03940e6e848983"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:9b0124b9c17e9890f0819b2e7a5f65ec9a2f5aabd6c8e7ad090c1675cf70dee6"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:23136f5a564654eb61061ec6d5620a4c1ea32c8f552b65e9982a12b72bff601b"}, + {file = "multidict-6.9.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f2524ec55b3e65cbe235a8b3c36e2af3b635be02ed05e20c94e70c5c943c009e"}, + {file = "multidict-6.9.1-cp314-cp314t-win32.whl", hash = "sha256:35ba0263bae5dd3ad5aad767cc9afc01a8598c7dae30f1b3b2de98b1b32c28bd"}, + {file = "multidict-6.9.1-cp314-cp314t-win_amd64.whl", hash = "sha256:7c8d5882ba25ac0282258be435d8a05aa0cbcacfce15799154a338f847f159b9"}, + {file = "multidict-6.9.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ac348379cf4de5538a0a213be1532d289aa801ec5d267c5909446b9ea2f8e2c3"}, + {file = "multidict-6.9.1-cp315-cp315-android_24_x86_64.whl", hash = "sha256:f04551dce5a7db8c9659f2e4245494c182d0663b83661803e08d46bfcae5eda1"}, + {file = "multidict-6.9.1-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:c0c88085affd35c33e124e36930c5ad96aff9294ce195eaa0fd9cec962b64a82"}, + {file = "multidict-6.9.1-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a8b75dd3d3638d9a19f23e84af4ffab3b8940422c0df2da2a77005ef5aa3d7ea"}, + {file = "multidict-6.9.1-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:006c4478de0a1876f4834e14255776286f09b9846b505fe63f67f9d173a9487c"}, + {file = "multidict-6.9.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:2784090c30a586d5b45197bd9c32f87fb927216cde302f6cfd76d76577e90f08"}, + {file = "multidict-6.9.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:7c708566da8014b120a64b1eb6d200c6c0c8cb36296383723cdb6fc82038270b"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:042fb0196047e786936a730bd302de83143950da45f2c16078da8f35e1cf7919"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2212a0c842c723d919ea4a22a9296cb6b244b386e4e6ea92adfc7fbf3095519"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd882aa29bf402b62bf1fd7c19fd5df4b6528cf468a908864b39368572b662a9"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c57541034d12b215ab0a2bfa371d1a8a198da18176d0426c27105b9161a6862d"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d73fed4e37158ff00cd271871170b79e40138db51e625fd352fa17c6acb34f67"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:79da2491348b30810728050b4a8ec0416f85884125c2fd44655b3d01150d9c3e"}, + {file = "multidict-6.9.1-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b4da208a63434d21a3df64d29758e650fc4aa8cb05848554b76949c296539cca"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:877ca17fdcfdf5c397493a71e5ff97a87bb181417fe717fdadc77c08c09301ac"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:40aec5299e1ed71fbb988389059da381c3c1a60e0c649acceb2a35d9b128848e"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:4a409ccc42aefec904038695d5d7fd6d8f3af2721b7b6401d55135ec7d6d298e"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:0a5769559e3312dd96731fbe15b4abb6033368ac1cad5a98dadd21946a4c7d6c"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:03fac50ddfd8302175b77863a015eccfae76767cda5506eef86df559ba861e1f"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:5ecace251ccfa705bf3d7d35c5032cf750f5c629809740405697bce5c118c4a4"}, + {file = "multidict-6.9.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:ecc89dbd4155b2f8a47f4bbd89242a35ed15e8e0ec581cab5ac65fa38407329d"}, + {file = "multidict-6.9.1-cp315-cp315-win32.whl", hash = "sha256:a3ffe881246d28a862f1985824f484cb7361f44d6b99c4c620436ef56462f38d"}, + {file = "multidict-6.9.1-cp315-cp315-win_amd64.whl", hash = "sha256:59c123d0e948d760a5f930f316cfefa07e8d632ab84327c0693ee6a88171154f"}, + {file = "multidict-6.9.1-cp315-cp315-win_arm64.whl", hash = "sha256:31199204b3ced121ff5407a2c342326a5d27e3870abbf94bd80dbd2451b7bc8f"}, + {file = "multidict-6.9.1-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:8879510a76940670517ea1cb589978da44b86e286ec3e50d664ef330817afce7"}, + {file = "multidict-6.9.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:aec65b53a07f580606593f877eefbb29a45939bfc0d3fe6e6d9f42b41b749f68"}, + {file = "multidict-6.9.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:14c56f73e78faa1f68bbb826197cd5871994e70e841b8590829c35912ece5c64"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:38c9986f9ce50c459b10de216a05f4bd7ed5ac63887d56e500a52bb464b861ce"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15db6a102cbaf1949cf028ecf080aac76d20bcd29ad4e092574db6c6b7af78a5"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bd82c4977196681a499bb6ca9e462afbc5c91c1c15b6a991dfbd72733fea4dd2"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bb58ba73a3f96f9a3e46b1fab69929d7edbbddb3133ee74b5c3c54074a53c4f1"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7c6eecfab7ce4cd9487ff8ba936fe38cdfd68c04faf3d5c710363c6a8e695659"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c62e71e6289d78c0108d8aeb495f8bd3cad4bc1632fedddc9297ddf287ecc20"}, + {file = "multidict-6.9.1-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:539c2cd5fed0947c135cd7eabaaac55f48300dfa1de0f3ca4edb5efa6606f471"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:3100d169ceb7bc8f05f89a6db11d1b21f119975fc26f29dc45a472e3569f0879"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:696477ad71385c4795e3b8e4cf10b0d2c28c2a1ca6a955e031cb1e62993e9ee3"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:f5844e7befc707367807586f550fa97e23dcfef0728f02b98c7bc498a961a5df"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:abc7c2e4b47bfe6a9aea434d3fdebb9597ee636e914e92ba352f2068b9142f4c"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:7ab379f95caee071a37cbd8be86d4c65accc651d391f9f97748fef006f38769c"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:557a4e1708df428ebe6c3081c83a273d275dad2446ce0d81fc648ac71afdb18d"}, + {file = "multidict-6.9.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:475d04d5192eba487a3e2f935976340baa24529046e9c1c9c7a3b7bf80445ae1"}, + {file = "multidict-6.9.1-cp315-cp315t-win32.whl", hash = "sha256:10083a8a0f4e1b26b599889e90b9802504ce5d3f7722f925bbb7ca47dd22a7c1"}, + {file = "multidict-6.9.1-cp315-cp315t-win_amd64.whl", hash = "sha256:e96ca64383efa107262ee3949f047af5ee4f1845ba09463466c04d35a83bd3ec"}, + {file = "multidict-6.9.1-cp315-cp315t-win_arm64.whl", hash = "sha256:501ed8b02a5990c67a91c732843609d43a6be1f7576fcdfc867331239f37fbd3"}, + {file = "multidict-6.9.1-py3-none-any.whl", hash = "sha256:7bf6478188f4e47bf5686e8a33da4ae28bf43b1b2528d9ee144d28492bfac60b"}, + {file = "multidict-6.9.1.tar.gz", hash = "sha256:0f06e60fa190aa7abd0914c2a766736fdc8e9f34878c4346338534b73d1b20e2"}, +] + +[[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 = ["dev"] +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.17.2" +description = "Convert Jupyter Notebooks (.ipynb files) to other formats." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "nbconvert-7.17.2-py3-none-any.whl", hash = "sha256:6a143c11c00bf831604da4b1be4347d36ea52367057eb920135d69bc2862fed2"}, + {file = "nbconvert-7.17.2.tar.gz", hash = "sha256:344a218e8595117ce37396ed025d994f146d076226ebac59255a2fa085ab24d8"}, +] + +[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", "intersphinx-registry", "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 = ["intersphinx-registry", "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 = "newrelic" +version = "10.17.0" +description = "New Relic Python Agent" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "newrelic-10.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91ebeaae460beaaeb3113474873bc5fc9c6c13ab6b0fd8936f584c508fec373d"}, + {file = "newrelic-10.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30b8b6a9f447a7276fd19a41ccc6dba264f9ef569e4bed92200a58b76e7f7754"}, + {file = "newrelic-10.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:214bd42ef8fb1c2046727bfe15c8f374ebf4ff2d5091ca1ac870abd2a7574ffe"}, + {file = "newrelic-10.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36a14fd92b44324d9bb33e1c1698c2cd15ffa0e291d222365e929ee17cd9d6da"}, + {file = "newrelic-10.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f62f70f1c01aa527de7e6ce2eb4c0285a7c40a89b42107be92bcc5dfd0fa8bb4"}, + {file = "newrelic-10.17.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54898db2b9eb81db9f3421302d2d03451630c033f2001fbe9f21d0e068f0418f"}, + {file = "newrelic-10.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d65f7d08f90caf6dd3708068a0eda8328c49ec18e51d514a43afaa5a68180e9c"}, + {file = "newrelic-10.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6dd61153b82b1e265754820f3e91c96c16b1b75508b6c169e27b5c196f1b7b95"}, + {file = "newrelic-10.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ab9cbce3f8da5bfcd085b8a59591cfb653d75834b362e3eccb86bdf21eea917"}, + {file = "newrelic-10.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:889969407457a9344927b1a9e9d5afde77345857db4d2ea75b119d02c02d9174"}, + {file = "newrelic-10.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d74c06863356b19c1fcf19900f85057ab33ef779aa3e0de3cb7e3d3f37ca8e20"}, + {file = "newrelic-10.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:083777458f93d16ae9e605fd66a6298d856e32deea11cf3270ed237858dcbfe6"}, + {file = "newrelic-10.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:165c7045da474342d4ceab67776e8aeb66e77674fab7484b4e2e4ea68d02ed4d"}, + {file = "newrelic-10.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3c3c82c95b57fe30fc1f684bf920bd8b0ecae70a16cc11f55d0867ffb7520d"}, + {file = "newrelic-10.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5789f739e6ca1c4a49649e406b538d67c063ec33ab4658d01049303dfad9398b"}, + {file = "newrelic-10.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4144dd96fa55772456326b3a6032a53d54aa9245ffc5041b002ce9eb5dbd0992"}, + {file = "newrelic-10.17.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c444e96918508decee6f532f04f0fa79027db0728770669ace4a7008c5dd52ca"}, + {file = "newrelic-10.17.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5171f1020bc834b01faae8466b5375e8c2162fa219c98430e42af1c6e5077b14"}, + {file = "newrelic-10.17.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0b43fb53f8a63c1e792a9ba4439680265b481c44efd64f7d92069e974c38b199"}, + {file = "newrelic-10.17.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:78a673440037ad61e0073da69f2549fac92271dadd7a2087c22a20ddc7f91260"}, + {file = "newrelic-10.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e81b726f3fab5fed155407f157ed67931d2d83403cc0ae473327e0b7b42bc5"}, + {file = "newrelic-10.17.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed6f549b1ab42ad31d5ee34c8041f1484ab769e045ad3b9f321c9588339079f3"}, + {file = "newrelic-10.17.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3a34df04ff6315619a8d098c59751f766de57f14e5cd5c09427dde47bfbc5012"}, + {file = "newrelic-10.17.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d92b43c07cf137d8a6d8dc73c87fbef99ca449564c25385e66727f156c2c34d8"}, + {file = "newrelic-10.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7669597193d8f6a3512fd5e8728a7b2b244db9694b3a03b3b99930ba9efc9e3b"}, + {file = "newrelic-10.17.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1027039eae1b4d3ffee3077135900a41ffdc41bd2bee3162d6cf36bd990cf3b"}, + {file = "newrelic-10.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:af28eb5e7f368f6f4fcde9593e7dd189b68e39a2e7409874a0cdea3a4bb4e904"}, + {file = "newrelic-10.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:328162a61e30f7b3e76241830989110d8f86d8392805a78034f8109e4f5434b4"}, + {file = "newrelic-10.17.0.tar.gz", hash = "sha256:f092109ac024f9524fafdd06126924c0fbd2af54684571167c0ee1d1cc1bcb7d"}, +] + +[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 = ["dev"] +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\" and sys_platform != \"emscripten\"" +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 = "pillow" +version = "13.0.0" +description = "Python Imaging Library (fork)" +optional = false +python-versions = ">=3.11" +groups = ["main"] +files = [ + {file = "pillow-13.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:6f38f3f885a09cafc93fd667b1173a92f379e43785d635e7983c893f0da319fb"}, + {file = "pillow-13.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37290fbef0c73e2d51d594eb78fded7dc7170d1c3ad0a890269e6fd8c8c4e061"}, + {file = "pillow-13.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c88c10dd432f3b39ccdafc9ed81d0c21b8fd634502574da76d1bfa4fe2c76d0"}, + {file = "pillow-13.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a625df9a2a5597fa5e5266e01aefc82604bb85d291e3547981e863560d75da6c"}, + {file = "pillow-13.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:10b5019883c98f1dd819ca48ffc6f33a91cee04948fe637c605f4345c7cafd6f"}, + {file = "pillow-13.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f391dc92a015c478745192fe4f2e120c2af2aba18d9fe0616341cbf537599806"}, + {file = "pillow-13.0.0-cp311-cp311-win32.whl", hash = "sha256:6a0920cb55df5a4d3f6862964908078c0bd59332bdd1bcd20d14e8c70ef27cc5"}, + {file = "pillow-13.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:d7710eb676e9bb68965cb045be0d333b4c0d7f9dfbaa7fbf121385b1588683d3"}, + {file = "pillow-13.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:12fbb851cf323cc19aac3eea1df5ad17b57e91e9fe3cfd06100dba7bb8208c13"}, + {file = "pillow-13.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:67c8d44ad89fa7eb88de5d6ef6199b1e03dd24974f85a67639fc8badb801fe79"}, + {file = "pillow-13.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc481f742ccda20e9ed760b8f978dff50f2a4e9bc253ac167fb0a05b0783ef52"}, + {file = "pillow-13.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8bf295fe459343bc6093c8e5e0df60bfa189e0fcb775a22e2c2488fdeccc6c0d"}, + {file = "pillow-13.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42d63be3af4f9b951b199b0a9d23365d37ab14687e6d77b74940432c8515c4ca"}, + {file = "pillow-13.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4bd024d567eca931b668978d672dba914d4b8e2628e2c3073a2ad178de8a2620"}, + {file = "pillow-13.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:23edf4ec4b6f4f240e8df6e4985e9ee2ced86474632433e55fb1e2548744bf40"}, + {file = "pillow-13.0.0-cp312-cp312-win32.whl", hash = "sha256:02464da86f561f410e13b061ec37c3068a9cb557a095494157742d07b3c24a27"}, + {file = "pillow-13.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:ff3fe9eb621fbb9db4c4be33ab946f6bac5f98ab50ca8d3260503653656c961b"}, + {file = "pillow-13.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:c3bc8ee0271387e0b1e3ad0ff893645990a656e79bf9c42f4f734a3642b11d51"}, + {file = "pillow-13.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:e98b4f91f99b24b1da72e10621ba181f7281922384a7403094debb4199de6c00"}, + {file = "pillow-13.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:34fb3db1149c879343861831728c243c432d4a5afc8f1878ca7612ef8de2a033"}, + {file = "pillow-13.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:2d50500a4a3bc6469adcdb319cf05d688b08ca3bf0f22a05339f3b25b433a599"}, + {file = "pillow-13.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ef5fe6b7db3f501c56000ba8fe7c7e1a35ca1d45824fbeb95a67daa85cff4dbe"}, + {file = "pillow-13.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f11a3c1358bb3c68012a7b1f41b223c3db9f7bfde90b481df028cfe1c3363313"}, + {file = "pillow-13.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19b66ca0a4d25cc0200b381ce824c7ea090db61427315e73cfb05dbf1b35c369"}, + {file = "pillow-13.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5f56499c1a74d2b862beb0c33b8016f99d095858455df9d21583bbbc1c15b582"}, + {file = "pillow-13.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2a14cd73d5e6c927f644b0110ee81f59c4ef506259ec9183904747f2caacc81"}, + {file = "pillow-13.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:08b826a9bf1265c76de04a42061d61ea6b109418b7826f28ff1ecdfaa26c5502"}, + {file = "pillow-13.0.0-cp313-cp313-win32.whl", hash = "sha256:12b0fa15879fe5a9d9eebe66e4e2d74128a773b1a4448010c9c714f45e04b9d8"}, + {file = "pillow-13.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:9dda0788a9932776a75d8bcc020076edc308ce2508b51f6739a45e3158b3fc42"}, + {file = "pillow-13.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:40a266371ece581e5de13b6635ef78d7487824af80561b6ca27694a88c19bc0f"}, + {file = "pillow-13.0.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:44629d4498c9cb6b2051806155f22141df0d8a929c56134b166655232dfb2f8c"}, + {file = "pillow-13.0.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:bf97ba1b5542050e9b0c74e632323b6d8136cc99d64e193abebee22fe6013c76"}, + {file = "pillow-13.0.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:aa694c49787040943570d61c9b8fc01271bd2a2cfdd55f0d896f8aecdce1a981"}, + {file = "pillow-13.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:49c12af515073e9bf511e4ef736743bf70d531a643668722279314b937742ba4"}, + {file = "pillow-13.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d9b0a2bee3f3e03e9f29057aedb807dbf1e1d96ee1b9d0f422d9db6c8583271d"}, + {file = "pillow-13.0.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5933fcea5a5ba64c686f55c886a115cbfd92f2900460784a1e79909fdbafd7b6"}, + {file = "pillow-13.0.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e91c2b1cbeae768c98752e67e717e283d68dae45717b41f2d91eaee648e37b7d"}, + {file = "pillow-13.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f6299e494e46253d40c34653cac369412f44ca53b5f85d848d3f95b1ed0546c"}, + {file = "pillow-13.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f9bd7d260d986f3553518c5d723544346fa48031f8aef3265d786aeb59845bc0"}, + {file = "pillow-13.0.0-cp314-cp314-win32.whl", hash = "sha256:2e31c4e68cffd7b1f116127626813b82fcba19edf6b940a7b0c266d6484d0055"}, + {file = "pillow-13.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:f7cbb7a64e7ec664775195e4f81923bc8a93d9451b963f844e59118f63147a7a"}, + {file = "pillow-13.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:a6aaa7871aebca081eb5c45f83e845bbd9712ae99fa9286dbfdcee835e63f4b4"}, + {file = "pillow-13.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7b999816b5850a35ada08443e6e03945f1f6488144a83afe2d37b240a552aafa"}, + {file = "pillow-13.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:67871a13cf47275201553b536c025da777f997fa562a19eb798af4ad4b97c18f"}, + {file = "pillow-13.0.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e8ca8f69b7c77fa96dad99f8638c1fc4f1c0bed4acaa1baf7a3c31bdb80a0ab1"}, + {file = "pillow-13.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6bce6a29c3898191f4c9998e4d4e8f69790caeabde46e54da4bc235ce5bde683"}, + {file = "pillow-13.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:816752a5ef76a80484c8c441c85593b7ea9304f6231fc5776ad1fbff7e773058"}, + {file = "pillow-13.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5bdb38ba220b61b4ec31dd1046dea6b016d3c6850a23f43ed8b58332b2fc668e"}, + {file = "pillow-13.0.0-cp314-cp314t-win32.whl", hash = "sha256:06903aac074d00c988e77a1fc435286dc498506d4ca8d6f69df9babddf4ecc15"}, + {file = "pillow-13.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9a635068d9793c7f0d929f39f18b58f1bd86c236e8e7b64167b86af9232ebca0"}, + {file = "pillow-13.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0d1a9cf7bc6917538b20f8d06b9ab2147e542f68849e96fc58eb66bdf6acc692"}, + {file = "pillow-13.0.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7d5e097eabd5d4915c27ac9f6e9325bb1e01a7c94d7348b5c4451d3fc30e8521"}, + {file = "pillow-13.0.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:51ebb529fc5e8abdd55302f6c3f8943037348ec2384329a3e55677f69ae2fdfc"}, + {file = "pillow-13.0.0-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:c87a04e7f152ee4db5dbe15f0bfa3fe628a1aeedbe66b81c43b87f52c813f9ac"}, + {file = "pillow-13.0.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:20722cd5375533ad754053363a80b8fb30c79d37930a6f7228030e237ce3bd5d"}, + {file = "pillow-13.0.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:04a63720f79e22fd54d897c233a68314c50ca0603360f54ce2bd5db8f0f43782"}, + {file = "pillow-13.0.0-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f8db54177035a2b5f717f94475b74907e12a96dc74f6d487f3966b0a4694071"}, + {file = "pillow-13.0.0-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f36aa77f74b14a2103622b196402c71330e4e7cf4122ee45c854e9a01e0eecf"}, + {file = "pillow-13.0.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:149a1c323ba366f90b48e6f1a6db6582eb50512df374588de56fc909abc0f0f3"}, + {file = "pillow-13.0.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e892354a424b1e82a78ba16785822bdd40de06f19446a3d4a28047df1a4f8932"}, + {file = "pillow-13.0.0-cp315-cp315-win32.whl", hash = "sha256:8e459b613cf31f8980f584387b4fe47bf08e076e288d61aa8eba1f7fd4ddbb81"}, + {file = "pillow-13.0.0-cp315-cp315-win_amd64.whl", hash = "sha256:d4737f50d23ddd11d6685faacbb9252887dde0bc7997127757247983d74399d6"}, + {file = "pillow-13.0.0-cp315-cp315-win_arm64.whl", hash = "sha256:2310e2adfc13c6d457d7d0f2ffdd5c56a74a317650cf765887df8d515a647ac0"}, + {file = "pillow-13.0.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:21c32061a5512dc13f87cc7303e120e4d77c2f70df89a35af0e3ce246e5ac57f"}, + {file = "pillow-13.0.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:1c774b9c0ba0d0b356f71530677b39028878a2cae5a93e0a13779cfd17120f88"}, + {file = "pillow-13.0.0-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20822140c9a2ba9c5e42df342b0a892ab2e102fc0e3db967a133bb9ce3f898bb"}, + {file = "pillow-13.0.0-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffea6b2986a797c84b6d1d27d4f43e0b83c73fc16281a930891cd237cf0d08fe"}, + {file = "pillow-13.0.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:05cd2cd39055d0b9650060e4513ef4a9a0aea870083950bd046a0d6490f93a22"}, + {file = "pillow-13.0.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:c6fd031333dedcad7ce3e03d244093f43504f209e86925ebdb2b868fa4037630"}, + {file = "pillow-13.0.0-cp315-cp315t-win32.whl", hash = "sha256:c50c80e3591e5cf9a8dfa6007d4f10732f02e32263850999286e56ccd650cfb2"}, + {file = "pillow-13.0.0-cp315-cp315t-win_amd64.whl", hash = "sha256:adb3c2124c68e480f4632d06cb7caa3b48a51678475f483b4edb1c6dee29ea43"}, + {file = "pillow-13.0.0-cp315-cp315t-win_arm64.whl", hash = "sha256:4a25756244bdcce3b50580baadf320fa48297f0eeb8e114ba64139a40d4d0fc8"}, + {file = "pillow-13.0.0-pp311-pypy311_pp80-macosx_10_15_x86_64.whl", hash = "sha256:405be6058e206a86fedce2f715ecc2343f94072d7925251632dffa2c05f70dca"}, + {file = "pillow-13.0.0-pp311-pypy311_pp80-macosx_11_0_arm64.whl", hash = "sha256:b84be41387fc00db28c13c02e30d42b02d8d8f6a4a741a1aee6012ca7f1f6039"}, + {file = "pillow-13.0.0-pp311-pypy311_pp80-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a192360d512305fe92d3053e4f7627bbad1f7708f1f4ad38cccd9336acabe9ad"}, + {file = "pillow-13.0.0-pp311-pypy311_pp80-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83b37abd87b590acd8f47ca8a61f70893322b11834d36e07c2298dacad4d14d2"}, + {file = "pillow-13.0.0-pp311-pypy311_pp80-win_amd64.whl", hash = "sha256:73ee25cf8cf8b75d5a5aeed7cb6588f5e5dbfbb0fde51707b630bbb23897645c"}, + {file = "pillow-13.0.0-pp312-pypy312_pp80-macosx_10_15_x86_64.whl", hash = "sha256:8619685cad8efc4c38c66d3b36aad854523297c43d748b3b6f0cc03c90ba3463"}, + {file = "pillow-13.0.0-pp312-pypy312_pp80-macosx_11_0_arm64.whl", hash = "sha256:7e91e97a929232cdb828889ee6ad0e48d7f40f4ec38818f4e4a8968b2b1af22e"}, + {file = "pillow-13.0.0-pp312-pypy312_pp80-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93ff9c9c3663ce23aaa5d0b6b6abac55359e2a0c06c7e30f3771829af816be63"}, + {file = "pillow-13.0.0-pp312-pypy312_pp80-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e65dd6e75de67b2362a4fa3e16aa627595f65054dc4ec73d64680c84d592fa61"}, + {file = "pillow-13.0.0-pp312-pypy312_pp80-win_amd64.whl", hash = "sha256:567f20f1c75897d7663830da6ea8af719e03d712b1d9ee7f813319f9ece42e5a"}, + {file = "pillow-13.0.0.tar.gz", hash = "sha256:cdcd1ba258178f7356d74170c9a81ba4eab6a5d55748bc402a5a2a6fe6be3510"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +test-arrow = ["arro3-compute", "arro3-core", "nanoarrow", "pyarrow"] +tests = ["coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "psutil ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "setuptools", "trove-classifiers (>=2024.10.12)"] +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", "dev"] +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.5.4" +description = "Accelerated property cache" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "propcache-0.5.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b77c313314524ca9c38fbd70f73515d04597ac58c40c939bc0e71eeb4abff680"}, + {file = "propcache-0.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8f911c395cef73c510bac566da9507bb6a43e7763d0c79138dc60ee53f11207e"}, + {file = "propcache-0.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d83b12902eb8bce151259c86c03ba746600b2d994543de46e370cecf96c452f2"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9281e922c072158c91974d4589f1dbe0fee6d467f284c28e463f9f5a4d933f4"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9f3551b8a35c1df3e7ea4d2d86edee15f0dde1bddd434a71744048683544d0ef"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ec6a85f424afa8d23e0d9a094e5dbb6eda01da91c92b9183cd433768247ffc97"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f574e460d1c8a08384a016fdb09ccf3543433263ed6b2f97104f979e64ea57c2"}, + {file = "propcache-0.5.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d8e017eeb7482bed34cdb0d61cf2bcfc88d104bbab296a17cd16a6af8aabc70e"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f273dcf7149a50527c4fd1f55cfe9eac0f60753f5af544b4c9352578e20c0874"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:fc2461ecc45f17893f8207e73b46ea8ba93e33630e51cf4af3fbc21d47462b1a"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:279655a16973f1ee2bd2fe79973137681642fd9ae0d89215bba263726eb0dc3a"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:e9f165403b81fea7e89c932d89046a1e3d9a3a60e8d7ef2f249dccdcb0982bf5"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1783582065a1f07f9d9ee1e992e13f15d7dc8fb1eb3a7476d43eb3f2e69d26bb"}, + {file = "propcache-0.5.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d605bb239b796e82a81c6709548b2bd460ab73b4590cb0c83de8a2dd9694d0f"}, + {file = "propcache-0.5.4-cp310-cp310-win32.whl", hash = "sha256:141fdbd73748db0cf7636035030aaac383d2efde8f34e7bc24594cc776d225b8"}, + {file = "propcache-0.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:146f48a9e4812611a7581003b1a39de56c34967046310c4171a68ef908c9a745"}, + {file = "propcache-0.5.4-cp310-cp310-win_arm64.whl", hash = "sha256:6c7599df2b57ebeea8de011b5f2f7b85de95e76037d43d34b95e328430275487"}, + {file = "propcache-0.5.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:897d1ddf6716e8f47200f7aad9a0efa6cc7586df66c6defa572f9eab379c078e"}, + {file = "propcache-0.5.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9cbfff4423eef4cc6cafc021469641a2b835f610b2647a6c5281903e21b8670d"}, + {file = "propcache-0.5.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3fc24f209c1b7f7f688b66b98293954f5504279760999b58920ee12dd8471c1d"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62530ca89187827e4a4fe733f971abe81a7542eeea48ff61995f19b64d7199c8"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fc3f7599528db40b1efa0889a620116e2704144495273d66066e8164e45838"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4f2d880ff60f45898f4acfa152aac8d04e3ee627d90ff4003491bf92239d5757"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e9368e87a3efc285e559131092c5db643eb8e56de4ee42064d5baec22ef2bb5"}, + {file = "propcache-0.5.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:004e685b315646c410771836e72a44f143bbe624f29653a42687815069a303d5"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:594eb4c6ec35e7179b058481f4e9f02521b56de16fa577c4b85c76fb1bf8a9f8"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:2dba2f02d2d5c09ef8a0e6c1a42aeaa451f4be9898cb00b04fe98717da2eb23b"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c3ef2818d63bc86071e9d2989ae75a1bc32b8f7059cfd9f5abbbee70c32e2ed6"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:dd2ac8f5b643454c2cc6b6118b13da16e88f4a6434fc3ba61aca384029f04f36"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4054acf80d40456a0537f2913b349718649d8d6458a14ab7f48d0ce28c30869d"}, + {file = "propcache-0.5.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40e94adb1e7d39ff28a8bd8d8b8fbd1df6b9f40976dbe379134f1ce058e532dd"}, + {file = "propcache-0.5.4-cp311-cp311-win32.whl", hash = "sha256:9f86f7259efe2c951f43e57d471c9b41daa5bfc7db9f67189059cf1ae6d77fd9"}, + {file = "propcache-0.5.4-cp311-cp311-win_amd64.whl", hash = "sha256:e904d4d01f36bd6e197590be1533c44e06058771e0746dd073a8ebb3ef880858"}, + {file = "propcache-0.5.4-cp311-cp311-win_arm64.whl", hash = "sha256:d42a9a856a4a6e2f6c10f1318c07e7daa498d6593abe745c71dae4521a26ca39"}, + {file = "propcache-0.5.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b28f41fa3b8c6900457f858ec5b03998f3a6d535fbc1bb2edec5961ea05ec429"}, + {file = "propcache-0.5.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:dcbf346a318a5e30063f547630b02bb787ce2f45b6368d5da143660b6a3835d8"}, + {file = "propcache-0.5.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:87a3caecf8095e48dc72f84bfa42e23a848cf410cc9cc13031fba4869b706a21"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60a64cbccaa11b7760ce705a14ada17ba459e7ca9f23ba587eb013821032d7ef"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a74bfa37147cc08fb29df10bd9c16f40fa7f860cd3a6d2fff853323a94f6e17f"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a4d7a54719b67338a305dca2ce6aafe366817df94ddfd4b5514374356f5ca546"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2814ecd8e818f487bee4b0f921bc4d1c176cc5fc71ac0f072d0fa67eda4ac14b"}, + {file = "propcache-0.5.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6af4693716bfb03f1752ef1b30faa593db2c01d5272e9b8564a1549452a979ab"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4fbc1a15dc8cd1689508758d626b372b1f09d28d9577667feaf9e6bfcd8efcbc"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cdee8205a44d0be91bbac4c41b95d86641b72dfc7aef1279400e4fda3f26a937"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9a2a8a50a93dee0268a860a07fa3b4bd968f8ce4dbd794957da772f395368526"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7ffafcbfc7b549ab940047e505c831eabac5e67de53e1bc174adbc5285c55944"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d1f5a500bfcbb2c0ab85e98a0dcd70f5899d34efe365a0187700369a79603031"}, + {file = "propcache-0.5.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a235f73d6e020855dc29dff012d920c02ee0feab8d73a24185a7569f4be1161"}, + {file = "propcache-0.5.4-cp312-cp312-win32.whl", hash = "sha256:b3083bfe87f95c756e610bd8025f26cbd1cd4aaa03a422f2d65efb7a97cd53d8"}, + {file = "propcache-0.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:98914de2c4d7f0f9f4a8c6ea4bf05841f4175796941e3ef7d47eb718f22311fb"}, + {file = "propcache-0.5.4-cp312-cp312-win_arm64.whl", hash = "sha256:8876b39961e33d912afe3c1bee18ee564fdad0206f873cc15d522756b7f50737"}, + {file = "propcache-0.5.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:36c0d9db44b523ef93d03341b1c42d69ff01d673c053d1b1c6c3a363bcaa39ba"}, + {file = "propcache-0.5.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1d52a05dc417279f7e5c7618c5dfbbc29923aaf9bc0a5c1802ddcebf54c61a0"}, + {file = "propcache-0.5.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44149f46500a0a41b95b4d99c2e586a77319539730607b9892974a092788b111"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dbab5f5ff6897c81f355d079010cdae85b02e5a0b518b5251523b8ad8ae9ac3c"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c3e98c55bde2bcf7db3c70d1aed7ae9aa8aebbf19a250c66645cde44cdb8b867"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db3ae52ccc150dbc84704e9d642743897f3e1c54742ff34cacb661e52e3818a9"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f85915e00dcb1cd9f2f890ead064ed40a27df06f0db65be427b29482ae357572"}, + {file = "propcache-0.5.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c2ba30a89035b57b73e00475de948521602f543d79ce01db10b04b36c4c76fc8"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ae58f361bd5dae942717c65d3413b478c70aea9c462599e7b9adad3731db3894"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:96f7c5c15656040ddcbc51e56dc59b58aa25999d743c126abd425b9766ab43e9"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7cc528e760a8af06f2b13e9b9f362cd90c7c718ea61228a96dbd31ba16ed7f47"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:425f8cc86ab5018b4b8d4a23bc8e74d964bd3d757c3702e301aa79be76c53f6c"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:a5793c7698a53f56f4a1889a4737c7eeb1b7ad0842fa6b1abca22913ff79c8c1"}, + {file = "propcache-0.5.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c02c0e570c5c7e077b0181a9f3cdb7d4c3617d1cda6b5c95bd5d34022923d82c"}, + {file = "propcache-0.5.4-cp313-cp313-win32.whl", hash = "sha256:3e413d7a4a9b4866b7a761d6060d434b64d23cd35122eda3b026a0bbe8196b25"}, + {file = "propcache-0.5.4-cp313-cp313-win_amd64.whl", hash = "sha256:0c889f6fa84957bc7e8b4eab71fd16a0455068d5045e3aa40c733071d2b2fd77"}, + {file = "propcache-0.5.4-cp313-cp313-win_arm64.whl", hash = "sha256:69fc35c0779522da366c563e5faf203ffc1f8ff0021d5b1337fa4efa5be73177"}, + {file = "propcache-0.5.4-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:e6720ba44ad7e72174314d0e1fb0172494cff5c73a3a8a2159c3d2402ff15565"}, + {file = "propcache-0.5.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4cfe0a92ae30151869e67a4b5f5e105e4e03ad30b3f38e5211b5bf77d0881993"}, + {file = "propcache-0.5.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d759d05634f1b038fb625a66662a8c85e5a8fec912da381b5149ddac107482b"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:251c63dd46a0659bb875cb254dc4c1e79ee91a847c737cd62373295afc2235dc"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7a8d5ff04eb1f85698a78d20c62a14676e7b960dcafde09a388d60ad377d355d"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b9100a93b372418d8688f3f2a3e5b45c64d70ca4d6176e121aca1e3bfc1e32f"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc07876cfb079b6f6f36d21ce75784ad6c2c6b563eeac0ed26c2fa2669b85df9"}, + {file = "propcache-0.5.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0951315a6b3142ee2167404d707743f0157c110091342b1aa0accac5cf0e4acf"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bee7d3aed13d56f54e681df38c3a23031bc9e3863f687d9d598825c9146acd7d"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4e985382be6d15da8d0c2710a6fa7b9070fc9ecdeefb7f580e88373984ec8be3"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:9e9ab13760aa8b6d0881ae7cb04fd891d8d490cd2554ea8e79bb278399169bcc"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:1b2f3bec4261a94019575481c726c29850f72e27907773c75b1de421e20e9f9d"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:720cf832eb2d0b0dfee129cb3335a26f6ce3cc45ee1187e8f0731758caa16792"}, + {file = "propcache-0.5.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fb0a5be8d9aa213150e8d8148a42aca4984b285bcad1e69587dc4298edd929b"}, + {file = "propcache-0.5.4-cp314-cp314-win32.whl", hash = "sha256:30cc1cebaf9aef49db06357a50398323ae04d70460c0491837d026ab7d6452ea"}, + {file = "propcache-0.5.4-cp314-cp314-win_amd64.whl", hash = "sha256:0a095db8e15a6020db149ecbed6461939fe74f6acaa3ae8b702a1fe8c38cd983"}, + {file = "propcache-0.5.4-cp314-cp314-win_arm64.whl", hash = "sha256:45488d1a5f9ab5bd90aaa1ca20f50fe1922b8ffad71a2009d2adf41355897aac"}, + {file = "propcache-0.5.4-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:53eaa697c4d0422ff4cb714d00231b43352064d97b944033b30c1d57cc506ec0"}, + {file = "propcache-0.5.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:886b59c4d28ca97dd23b025fdfc50a0356be934efbbbca89ad26230067f86fe5"}, + {file = "propcache-0.5.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fa15757fea1dfcd5b7745cad9f4638929605531bd4018ab2adff7955f1a403d"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6f0093ac3e9daada202c2082439d414a625c57184727a46e112a3fb2a81cb788"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3cd3a7edb6b95b9b33998135ebfa18d709da82290fb8f27c858970b5a12c8b56"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c174bfd1c48a1b51a3078e95586dde718374bac79719ab3541ec9e74aec40574"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a219f0ac59817a9114dd2aa57c13180f993e819ba658c7ddab4b66ed1ee0d370"}, + {file = "propcache-0.5.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:17a7400cec0256f0a71ae71f9da398f9894c956ff6668a1c9d317b3367316320"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:978f28401afbc76cdc3df9e1717b4229a06b626a1dcc75db4e1f2beb3884c3e9"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4a1f4f5ffa55dce6307631f3cb2948e117e665966ea512e0d502b16c24f567e7"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:213bb68d9ced5cf2bf717b1071bf2b09b4b04c426256f9fe6d054c60318424c4"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:286867fb156488c251a3721766e380ac4495e4fd6b51aaa1403d89ce7f4359d9"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:445ee3bfb46e85838387fb3c536a73cc0b994dc192b004e40e170adc54aa2a7e"}, + {file = "propcache-0.5.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:48cb48c5346a97de792254af77715aa2529c2a1ebc5f586aa0aae44a02f1fe57"}, + {file = "propcache-0.5.4-cp314-cp314t-win32.whl", hash = "sha256:03b229037d25b801e7af53fd52b9fc49d9439b036fca1e087e02780631adfa97"}, + {file = "propcache-0.5.4-cp314-cp314t-win_amd64.whl", hash = "sha256:8a1fc236528c457cd739c88abe823da851b7ab645d72792f88658114cc340c12"}, + {file = "propcache-0.5.4-cp314-cp314t-win_arm64.whl", hash = "sha256:135036c5cfc93864affb0f9af9a27e5d7a71cb7bd745e7b6dbfc2d56cc30e827"}, + {file = "propcache-0.5.4-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:45bf2e730ab8905d0527fe05a86500f406e64305c34cc81ebe64b4617cab9760"}, + {file = "propcache-0.5.4-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:31eb43ba2edc704ab2ec27815315dd8a19def0fb16215be4cfe8d32fe78ffd51"}, + {file = "propcache-0.5.4-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:174507f82d3594622acb1dd2dafecf2d899d6d506335494e7107767bf05f3aae"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50e337653721d20ead710da33bf44487fbe8a0db8782714b60306481e9f95b51"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0d21d0d2c82bbfeb1677a9711f38df968f9837576102bb4add1bd449d28d88f1"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccf4f7a79e26bb7efb06ecd50c177833b71df05cbc748701372325e6bcc17f6f"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23278f808cd81d5ada7184a76606b925fb3389c60e1077b2cd7da7b1fcf0553c"}, + {file = "propcache-0.5.4-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e738ab81179510ce79b2eac9a6ecf47feffd9e76d1c72e403005dddb6e36c06c"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:a419ee85e654927baabda3929c03c0cc1112bf472ff0dfd6142f4e3a81ca4162"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:b61805357d966680acf68b3b6d49772631ed9df44ebece10ff1460e117a7da8a"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:58134228927cee6c047d626c08e60a81be604a20578a12ce752cc5c9a84d4826"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:350b272b2279f4135a64fc0c304a5d08e28a137c9573442c606152446638a831"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:45bebbe252550fec975ba3b62bc6f931643cfd3b5464ef47619cf3fef154e01c"}, + {file = "propcache-0.5.4-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:ada748108a43d29b7c328ba7db3755327cd94f028bcc1a7ee3f0addcfacd9c38"}, + {file = "propcache-0.5.4-cp315-cp315-win32.whl", hash = "sha256:ee19113bce2f3acd46432050688b70f61acd6857d75abb9ec96341b7e9ced123"}, + {file = "propcache-0.5.4-cp315-cp315-win_amd64.whl", hash = "sha256:ceb3e879afac028f93d272c957814695dc5569e4904262dbee92f6c41bd5e4a3"}, + {file = "propcache-0.5.4-cp315-cp315-win_arm64.whl", hash = "sha256:c83acbce9f2b5e3f5f5eda9e53d2001fed22fcdfef81274a9e02d8fd53b70a30"}, + {file = "propcache-0.5.4-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:a5e8ef588c109725dc713ba69aadcac00a1ef90c2ce9c0a8c7075128f569f47f"}, + {file = "propcache-0.5.4-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:4d86476a935c88963d9b8e1a9a0d38188790e9622169bfbafa173046846709d3"}, + {file = "propcache-0.5.4-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:f5470694918830da62fac9e69133b53d23b736d7070e587b27a4a2be37e08e68"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10ef33a68a61ce317e095fd2e202a592ea92392b90944a78c993f0d9a73ab06c"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5cacf3c9efd09df409dc33654dd077e1c245ba8fb747b0f0236ef41b7c49b589"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:770e8209d018175fc0063936fa9583b6d27e88c5ad31543f3383d66080efdd62"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03969626faf0783a592dfa17e28eac06018bd0b44dafae6943d53b92421a7f72"}, + {file = "propcache-0.5.4-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ef3b928d9c984322b5c44e6964d8dbc653da87d2d8ee1647fa6da43072e650a9"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:7177c43eddf10a0893c4fec52ebb408fdcd7f7d63962caace9180d8f81b14ece"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:420162a77f94eb1cf5ef7893f500016dabd548e73de956785a1dd899cc73006a"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:3eb2e820e8e2101407da93f17c57cbb7d225461955fc60105daaba14cd421ee2"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:13e52b6e0bde97dee98ab66552dbff2931649c96f1ac432eac299fe689ec373b"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:12682126712ddc19b70ff819debbd279e58adf1f0c8f8f8138c18ade2044b284"}, + {file = "propcache-0.5.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:3af0c8642b2da4815d86e631232ac8286e17644fad907c19508aa8e7cb4ba8ad"}, + {file = "propcache-0.5.4-cp315-cp315t-win32.whl", hash = "sha256:1df8d8561b21465c5dd56110a01caf897e026d065b4b84e98a488209094272ec"}, + {file = "propcache-0.5.4-cp315-cp315t-win_amd64.whl", hash = "sha256:02c0a34f16889cf800f10f0247a564d8ce6eeab6ffcd7c87198f769067eb8432"}, + {file = "propcache-0.5.4-cp315-cp315t-win_arm64.whl", hash = "sha256:dc4242ca653c9b30ab51c5f8193323e7bc0928f897ee9103201e59a43abcb72e"}, + {file = "propcache-0.5.4-py3-none-any.whl", hash = "sha256:62c60aec739ed00124573cce1178138fd690c7676352d67a37328c1cf51d7468"}, + {file = "propcache-0.5.4.tar.gz", hash = "sha256:ff6b113f50bc066a698db5d944d2c6dc7507168dd3341e255a8892fd0715a558"}, +] + +[[package]] +name = "psd-tools" +version = "1.24.0" +description = "Python package for working with Adobe Photoshop PSD files" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "psd_tools-1.24.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:55611a5bf04ea767b28ba9cde49c73ebd8eddac39129946bf5d859ee9dabe1a9"}, + {file = "psd_tools-1.24.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed5355b65ca3a1d692f07e0e553a010647ba1e1d5166856d5707c2687c41954b"}, + {file = "psd_tools-1.24.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a6bd25a1952c3ca9158f0ca1d2cdca8c94478a882f86e616ac2132036d2b4f9"}, + {file = "psd_tools-1.24.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c63093ca885228bdecf34dcfc6509e5ca68b14e86de4556ca44912479fcfc069"}, + {file = "psd_tools-1.24.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8f4bf7c542f15325efbe87f076f5bb50634347a03490486138905fa495389711"}, + {file = "psd_tools-1.24.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f33945c0e775b7140abfbb9e958293242831a3c622ca2409d21dedc5d750ac3e"}, + {file = "psd_tools-1.24.0-cp310-cp310-win_amd64.whl", hash = "sha256:43d5ee009ad88bc4f407f041175ccbd053f6dc3aa7d79891a6a972d9afa5195e"}, + {file = "psd_tools-1.24.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:828945b74f369774ef351aaa9fa66709d24dca4f539307d83324cc1f7336e872"}, + {file = "psd_tools-1.24.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab79069ca9f0a946c982a656b4ee08b05a4239d006141c47dd9821e17457fe3e"}, + {file = "psd_tools-1.24.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0453d0f21b1ad72e54db6c90c8ae2ffad27a1d3a2c20d24fd37a41b877d83d7"}, + {file = "psd_tools-1.24.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb761ae1d42922b71144f5ce61a42c6081f09877f25b1688295a902bf77d8586"}, + {file = "psd_tools-1.24.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3f2954187d40dec34174a727ba7af354e5a0ab6051cba335a1a04b6630d6522c"}, + {file = "psd_tools-1.24.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fc005ee07879ec9e9de59f6e4d5f6c13b956092f35cafd734f03f5d370a2fa5"}, + {file = "psd_tools-1.24.0-cp311-cp311-win_amd64.whl", hash = "sha256:c19aa276a2f52362ac320bbb8ee0de64d54c0d634874e63a6b3cf75e18020a68"}, + {file = "psd_tools-1.24.0-cp311-cp311-win_arm64.whl", hash = "sha256:4a871ecd9b2552a3a74d7e1154b31734f03403d6659960186d33d5e19020b1c0"}, + {file = "psd_tools-1.24.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7a27e0593dda4bab97f751d73e7e26e82d5cc37fadd0be67f885fa756521c4e7"}, + {file = "psd_tools-1.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:505af5cba340642ca753731e345b50630e3ad750c008978b9216fa3a1a8f6485"}, + {file = "psd_tools-1.24.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79496ed64ff30a0d2c91cecc56c8280e9c239b4d82abc67a2658d60202f5d3f"}, + {file = "psd_tools-1.24.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a35dcd86a840af544d287f6390f73123f2ee4f464268c89502e6c13d868725d"}, + {file = "psd_tools-1.24.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e7b4e20edbf308b03e1c6ae681e2958bd4bd29f8fd271e042e2608b97ca3cfb7"}, + {file = "psd_tools-1.24.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e34717283d0fb0121db3a45a5e53a135913da2970960a8c79d11e3c5205f68f0"}, + {file = "psd_tools-1.24.0-cp312-cp312-win_amd64.whl", hash = "sha256:f43134cd0ab7ad963be7240676d21acca7cc6d16c6bbac28cdbcf44695305128"}, + {file = "psd_tools-1.24.0-cp312-cp312-win_arm64.whl", hash = "sha256:26532427d1d4e54270d25223b7e5d13f02b666b7ce3304912c801c868ae1dfa5"}, + {file = "psd_tools-1.24.0-cp313-abi3-macosx_10_13_x86_64.whl", hash = "sha256:907f6d89d673638e0fb9ca8c236609804c665a36c067484b8f0c990501b98a6b"}, + {file = "psd_tools-1.24.0-cp313-abi3-macosx_11_0_arm64.whl", hash = "sha256:7b591cd96e28f802f23f1e2be1b5c77c5b1a063a197126c3ad82470f4e83c7d5"}, + {file = "psd_tools-1.24.0-cp313-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a53951a0bbb885d7d63de4714c342f4ff939194420bb6c91deb0b0968bab776c"}, + {file = "psd_tools-1.24.0-cp313-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e720584da6da51cff560f4e28b57b124d83253df080259304382bb7914955a2"}, + {file = "psd_tools-1.24.0-cp313-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ca9801e7b8c788c1a91b4b2c9d636202935ebe0c1fc29c45eade8aada544678b"}, + {file = "psd_tools-1.24.0-cp313-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:64cf5a6fee279b71178fdc906df4c94ad30c1bcdf3518d30b4fdeda8683cacc0"}, + {file = "psd_tools-1.24.0-cp313-cp313-win_amd64.whl", hash = "sha256:98420616dc86acb114c2e19d4035ad3b5a6750fef3183ef92eb38c9052cb278a"}, + {file = "psd_tools-1.24.0-cp313-cp313-win_arm64.whl", hash = "sha256:a9f11bd6b615c00dac2a52a8c44d4c7e69aa17a84a80b61199d49a6ce162a68e"}, + {file = "psd_tools-1.24.0-cp314-cp314-win_amd64.whl", hash = "sha256:85d8b044984a3c1a7c2e2f121dd32e9297294b629dd5f908042d3a8640134de3"}, + {file = "psd_tools-1.24.0-cp314-cp314-win_arm64.whl", hash = "sha256:6972ad1c53db948d36cf3e3e6e15496a103b9f065e6087b5a810adf7f937dc1f"}, + {file = "psd_tools-1.24.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e0f83a82d223d8e000c0921660f7fd396f299d4f23e95e03bd0ecc980cb610f0"}, + {file = "psd_tools-1.24.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a176bd666f371ed35b1bc47cc48198758c8cf2d8baff6ba092dcbbcf55355072"}, + {file = "psd_tools-1.24.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:633c554d75306a549f4ced43771d9d52090caf04508d8f27bf02119e24bbd18f"}, + {file = "psd_tools-1.24.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:452400265d4a219889d27f0cc908923ba49e7295208fb8c404cc1cc05ac9e441"}, + {file = "psd_tools-1.24.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:81391b10e6866a8952d551040cbe82f1a3d37a0d0b216a05d627580c8d85a3f1"}, + {file = "psd_tools-1.24.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e553859e4774ce2db952e5d71dfc3ce5da13b1b1732436472c8c58ff90f053c2"}, + {file = "psd_tools-1.24.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9c2a2a1035f674c496a8a9f13fb212d879a3a2617534b3ca0f8471e5c9eb3cf0"}, + {file = "psd_tools-1.24.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f50fd7c13b7b838319c5351c4c1a7c25a5baba3b4c8a9edf0c2782cae248937c"}, + {file = "psd_tools-1.24.0-cp315-cp315-win_amd64.whl", hash = "sha256:38e6ce6acbdc5b9f70728081597cbbfdb71ef6de718c339993ce9aeafd37253d"}, + {file = "psd_tools-1.24.0-cp315-cp315-win_arm64.whl", hash = "sha256:fd373881b5880044a0569595d63c82d173df016521eeb681ff2da9e89802ce11"}, + {file = "psd_tools-1.24.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:b1f360646fd0d71b2b48b5e0efc90e265c2ee7c57d28ea57c64f67a6b641aff6"}, + {file = "psd_tools-1.24.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:1dfa5ea820f320d08502f5678202f5f4f2aee095376bbd7eb9f8650937f30901"}, + {file = "psd_tools-1.24.0-cp315-cp315t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86905b27d184efd6252aa2f6fe3b6e7f702ce71c602de942df4eacb360b0a81f"}, + {file = "psd_tools-1.24.0-cp315-cp315t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59164ddd6686d904ef4d8794a436b902749d12ae751c929814e5ac43a916872b"}, + {file = "psd_tools-1.24.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:dc0fc45bea8d53da0832dfc876f47b24a074efbc68cc0a785b37884ba85ed7b4"}, + {file = "psd_tools-1.24.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:178d96be6cf895d5837ec045bb0c12590942f282bc6d02dac6a4793a7d3b7124"}, + {file = "psd_tools-1.24.0-cp315-cp315t-win_amd64.whl", hash = "sha256:91a9fcb4dca4c5502fbd40a571387d8a54901e991bbb36c4802477c1d80be6fe"}, + {file = "psd_tools-1.24.0-cp315-cp315t-win_arm64.whl", hash = "sha256:ecea3518fab75caa34d3af3bcf1a64d25eb6b8afc4d643e586cf148383cfe77e"}, +] + +[package.dependencies] +attrs = ">=23.0.0" +numpy = ">=1.22" +Pillow = ">=10.3.0" +typing-extensions = ">=4.0" + +[package.extras] +composite = ["aggdraw (>=1.3.16) ; sys_platform != \"win32\"", "aggdraw (>=1.3.16,<1.4.1) ; sys_platform == \"win32\" and python_version < \"3.11\"", "aggdraw (>=1.4.1) ; sys_platform == \"win32\" and python_version >= \"3.11\"", "scipy (>=1.9)"] + +[[package]] +name = "psutil" +version = "7.2.2" +description = "Cross-platform lib for process and system monitoring." +optional = false +python-versions = ">=3.6" +groups = ["main", "dev"] +markers = "sys_platform != \"emscripten\" and sys_platform != \"cygwin\"" +files = [ + {file = "psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b"}, + {file = "psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea"}, + {file = "psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63"}, + {file = "psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312"}, + {file = "psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b"}, + {file = "psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9"}, + {file = "psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00"}, + {file = "psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9"}, + {file = "psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a"}, + {file = "psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf"}, + {file = "psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1"}, + {file = "psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841"}, + {file = "psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486"}, + {file = "psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979"}, + {file = "psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9"}, + {file = "psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e"}, + {file = "psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8"}, + {file = "psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc"}, + {file = "psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988"}, + {file = "psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee"}, + {file = "psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372"}, +] + +[package.extras] +dev = ["abi3audit", "black", "check-manifest", "colorama ; os_name == \"nt\"", "coverage", "packaging", "psleak", "pylint", "pyperf", "pypinfo", "pyreadline3 ; os_name == \"nt\"", "pytest", "pytest-cov", "pytest-instafail", "pytest-xdist", "pywin32 ; os_name == \"nt\" and implementation_name != \"pypy\"", "requests", "rstcheck", "ruff", "setuptools", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "validate-pyproject[all]", "virtualenv", "vulture", "wheel", "wheel ; os_name == \"nt\" and implementation_name != \"pypy\"", "wmi ; os_name == \"nt\" and implementation_name != \"pypy\""] +test = ["psleak", "pytest", "pytest-instafail", "pytest-xdist", "pywin32 ; os_name == \"nt\" and implementation_name != \"pypy\"", "setuptools", "wheel ; os_name == \"nt\" and implementation_name != \"pypy\"", "wmi ; os_name == \"nt\" and implementation_name != \"pypy\""] + +[[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\" and sys_platform != \"emscripten\"" +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 = "pure-eval" +version = "0.2.4" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +groups = ["main", "dev"] +files = [ + {file = "pure_eval-0.2.4-py3-none-any.whl", hash = "sha256:96cae060a313cfaad51bb761278bfb0e62dc0248d9315a81173752dc546cd37a"}, + {file = "pure_eval-0.2.4.tar.gz", hash = "sha256:260c2774686e651b79f8b8e7fc9d80b3599ea6a66334b47d5f4abb69fc2c0ea1"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pyasn1" +version = "0.6.4" +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.4-py3-none-any.whl", hash = "sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b"}, + {file = "pyasn1-0.6.4.tar.gz", hash = "sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81"}, +] + +[[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.21.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.9" +groups = ["main", "dev", "docs"] +files = [ + {file = "pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9"}, + {file = "pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c"}, +] + +[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 = ["dev"] +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", "dev"] +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 = "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"] +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 = "3.0.3" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.11.5" +groups = ["main", "dev"] +files = [ + {file = "soupsieve-3.0.3-py3-none-any.whl", hash = "sha256:fa30e3ba4809cb81ce1f3209f2fbe3e779fc445f0439bc147a0d7c4601743f21"}, + {file = "soupsieve-3.0.3.tar.gz", hash = "sha256:7dcf6022eed0399eb9934a75e020148f7a2024c37b7dfcd3cf2c5505d69c364e"}, +] + +[[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 = "stack-data" +version = "0.6.3" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +groups = ["main", "dev"] +files = [ + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + +[[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 = "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.8.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.10" +groups = ["main", "dev", "docs"] +files = [ + {file = "urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3"}, + {file = "urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63"}, +] + +[package.extras] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] + +[[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 = "26.6.1" +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.17.0" +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 = "26.6.1" +resolved_reference = "015a87ffd143871372f6f68a2a11858ce1fb08eb" + +[[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 = "eba60935938c3b2dd8f73cf1a0467f34f54c04905b3f3fb98ef6339d4560e56b" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..67624a235 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,899 @@ +[tool.poetry] +name = "mfr" +version = "26.2.1" +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.4.3" +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.21.0" +olefile = "0.47" +Pillow = "13.0.0" +psd-tools = "1.24.0" +ipython = "9.17.1" +nbconvert = "7.17.2" +nbformat = "5.10.4" +traitlets = "5.14.3" +jsonschema = "4.24.0" +jinja2 = "3.1.6" +mistune = "3.3.4" +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.11" +certifi = "2025.1.31" +unoserver = "3.3.2" +openpyxl = "^3.1" + +waterbutler = { git = "https://github.com/CenterForOpenScience/waterbutler.git", tag = "26.6.1" } +markupsafe = "2.0.1" +celery = "5.5.0" +celery-amqp-backend = "^1.2.0" +newrelic = "10.17.0" + + +[tool.poetry.group.dev] +optional = true + +[tool.poetry.group.dev.dependencies] +black = "^25.1.0" +isort = "^6.0.1" +ruff = "^0.12.7" +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 5bb150968..000000000 --- a/requirements.txt +++ /dev/null @@ -1,57 +0,0 @@ -aiohttp==0.22.5 -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.2.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.4.0 - -# 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 - -# Issue: certifi-2015.9.6.1 and 2015.9.6.2 fail verification (https://github.com/certifi/python-certifi/issues/26) -certifi==2015.4.28 diff --git a/setup.cfg b/setup.cfg index f4a03a181..71600054c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,7 +8,7 @@ [flake8] ignore = E501,E127,E128,E265,E301,E302,F403,E731 max-line-length = 100 -exclude = .ropeproject,tests/*,src/*,env,venv,node_modules/* +exclude = .ropeproject,tests/*,src/*,env,venv,node_modules/*,.github/scripts/ci/render-trivy-report.py -[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 ecfe3aebd..000000000 --- a/setup.py +++ /dev/null @@ -1,819 +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.5', - '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', - '.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/supportedextensions.md b/supportedextensions.md index 9c6ae1991..accac36da 100644 --- a/supportedextensions.md +++ b/supportedextensions.md @@ -116,6 +116,7 @@ Some file types may not be in the correct list. Please search for the file type * .bf * .bib * .bmx +* .boa * .boo * .boxs * .bro diff --git a/tasks.py b/tasks.py index 96a0a5a1e..13ceb3f1f 100644 --- a/tasks.py +++ b/tasks.py @@ -1,51 +1,27 @@ import os +import sys from invoke import task WHEELHOUSE_PATH = os.environ.get('WHEELHOUSE') -CONSTRAINTS_FILE = 'constraints.txt' - - -def monkey_patch(ctx): - # Force an older cacert.pem from certifi v2015.4.28, prevents an ssl failure w/ identity.api.rackspacecloud.com. - # - # SubjectAltNameWarning: Certificate for identity.api.rackspacecloud.com has no `subjectAltName`, falling - # back to check for a `commonName` for now. This feature is being removed by major browsers and deprecated by - # RFC 2818. (See https://github.com/shazow/urllib3/issues/497 for details.) - # SubjectAltNameWarning - import ssl - import certifi - - _create_default_context = ssl.create_default_context - - def create_default_context(purpose=ssl.Purpose.SERVER_AUTH, *, cafile=None, capath=None, cadata=None): - if cafile is None: - cafile = certifi.where() - return _create_default_context(purpose=purpose, cafile=cafile, capath=capath, cadata=cadata) - ssl.create_default_context = create_default_context @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 @@ -62,21 +38,19 @@ 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) @task def server(ctx): - monkey_patch(ctx) - if os.environ.get('REMOTE_DEBUG', None): import pydevd # e.g. '127.0.0.1:5678' @@ -85,3 +59,40 @@ 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) + + +@task +def newrelic_init(ctx, key=None, verbose=False): + if key is None: + sys.exit('No newrelic api key given. Please generate one and rerun this command ' + 'with `invoke newrelic-init --key=$key`') + + cmd_tmpl = 'newrelic-admin generate-config {} newrelic.ini' + cmd = cmd_tmpl.format(key) + if verbose: + print(cmd_tmpl.format('')) + ctx.run(cmd, pty=True) + + +@task +def newrelic_server(ctx, config='newrelic.ini', verbose=False): + if not os.path.exists(config): + sys.exit("Couldn't find config file '{}'. Check path or run `invoke newrelic_init` " + "to generate it.".format(config)) + + cmd = f'poetry run env NEW_RELIC_CONFIG_FILE={config} newrelic-admin run-program invoke server' + if verbose: + print(cmd) + ctx.run(cmd, pty=True) 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..0045dbece 100644 --- a/tests/core/test_utils.py +++ b/tests/core/test_utils.py @@ -1,39 +1,75 @@ import pytest -import pkg_resources +from importlib.metadata import entry_points 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 + +@pytest.mark.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 + + +class TestClientSession: + + def test_session_is_shared_and_keeps_no_cookies(self): + import asyncio + import aiohttp + + async def check(): + first = mfr_utils.get_client_session() + second = mfr_utils.get_client_session() + assert first is second + assert isinstance(first.cookie_jar, aiohttp.DummyCookieJar) + await mfr_utils.close_client_session() + assert first.closed + third = mfr_utils.get_client_session() + assert third is not first + await mfr_utils.close_client_session() + + asyncio.run(check()) 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 '