diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 872e8627..00000000
--- a/.coveragerc
+++ /dev/null
@@ -1,10 +0,0 @@
-[run]
-source = pya
-
-[report]
-exclude_lines =
- # Have to re-enable the standard pragma
- pragma: no cover
-
- # Don't complain if tests don't hit defensive assertion code:
- raise NotImplementedError
diff --git a/.github/workflows/pya-ci.yaml b/.github/workflows/pya-ci.yaml
index 766bac75..9ec602d0 100644
--- a/.github/workflows/pya-ci.yaml
+++ b/.github/workflows/pya-ci.yaml
@@ -1,51 +1,126 @@
-name: Pya
+name: test-and-publish
on:
push:
- branches:
- - master
- - develop
- pull_request:
- branches:
- - master
- - develop
+ # Avoid using all the resources/limits available by checking only
+ # relevant branches and tags. Other branches can be checked via PRs.
+ branches: [main]
+ tags: ['v[0-9]*', '[0-9]+.[0-9]+*'] # Match tags that resemble a version
+ pull_request: # Run in every PR
+ workflow_dispatch: # Allow manually triggering the workflow
+ schedule:
+ # Run roughly every 15 days at 00:00 UTC
+ # (useful to check if updates on dependencies break the package)
+ - cron: '0 0 1,16 * *'
+
+permissions:
+ contents: read
+
+concurrency:
+ group: >-
+ ${{ github.workflow }}-${{ github.ref_type }}-
+ ${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
jobs:
- unit-test:
- runs-on: ${{ matrix.os }}
- timeout-minutes: 120
+ prepare:
+ runs-on: ubuntu-latest
+ outputs:
+ wheel-distribution: ${{ steps.wheel-distribution.outputs.path }}
+ steps:
+ - uses: actions/checkout@v5
+ with: {fetch-depth: 0} # deep clone for hatch-scm
+ - uses: astral-sh/setup-uv@v8.1.0
+ - name: Run static analysis and format checkers
+ run: uv run pre-commit run --all-files --show-diff-on-failure
+ - name: Build package distribution files
+ run: uv run tox -e clean,build
+ - name: Record the path of wheel distribution
+ id: wheel-distribution
+ run: echo "path=$(ls dist/*.whl)" >> $GITHUB_OUTPUT
+ - name: Store the distribution files for use in other stages
+ # `tests` and `publish` will use the same pre-built distributions,
+ # so we make sure to release the exact same package that was tested
+ uses: actions/upload-artifact@v4
+ with:
+ name: python-distribution-files
+ path: dist/
+ retention-days: 1
+
+ test:
+ needs: prepare
strategy:
matrix:
- os: ["ubuntu-latest", "macos-latest"]
- python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
+ python:
+ - "3.11"
+ - "3.12"
+ - "3.13"
+ - "3.14"
+ platform:
+ - ubuntu-latest
+ - macos-latest
+ - windows-latest
+ runs-on: ${{ matrix.platform }}
+ steps:
+ - uses: actions/checkout@v5
+ - uses: astral-sh/setup-uv@v8.1.0
+ with:
+ python-version: ${{ matrix.python }}
+ - name: Install portaudio Ubuntu
+ if: matrix.platform == 'ubuntu-latest'
+ shell: bash -l {0}
+ run: sudo apt-get install portaudio19-dev
+ - name: Install portaudio MacOS
+ if: matrix.platform == 'macos-latest'
+ shell: bash -l {0}
+ run: brew install portaudio
+ - name: Retrieve pre-built distribution files
+ uses: actions/download-artifact@v4
+ with: {name: python-distribution-files, path: dist/}
+ - name: Run tests
+ run: >-
+ uv run tox --installpkg '${{ needs.prepare.outputs.wheel-distribution }}'
+ -- -rFEx --durations 10 --color yes # pytest args
+ - name: Upload partial coverage report
+ uses: coverallsapp/github-action@master
+ with:
+ path-to-lcov: coverage.lcov
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ flag-name: ${{ matrix.platform }} - py${{ matrix.python }}
+ parallel: true
+
+ finalize:
+ needs: test
+ runs-on: ubuntu-latest
+ steps:
+ - name: Finalize coverage report
+ uses: coverallsapp/github-action@master
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ parallel-finished: true
+ - name: debug
+ run: echo "ref=${{ github.ref }} event=${{ github.event_name }}"
+
+
+
+ publish:
+ needs: finalize
+ if: ${{ (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && contains(github.ref, 'refs/tags/') }}
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
steps:
- - uses: actions/checkout@v3
- - name: Install portaudio Ubuntu
- if: matrix.os == 'ubuntu-latest'
- shell: bash -l {0}
- run: sudo apt-get install portaudio19-dev
- - name: Install portaudio MacOS
- if: matrix.os == 'macos-latest'
- shell: bash -l {0}
- run: brew install portaudio
- - uses: conda-incubator/setup-miniconda@v2
- with:
- miniconda-version: "latest"
- activate-environment: test-env
- environment-file: ci/test-environment.yml
- python-version: ${{ matrix.python-version }}
- auto-activate-base: false
- - name: Set up depen
- shell: bash -l {0}
- run: |
- conda init bash
- conda config --add channels defaults
- conda activate test-env
- conda install ffmpeg coverage python-coveralls --file=requirements_remote.txt --file=requirements_test.txt
- # pyaudio is not yet available on conda
- pip install -r requirements.txt
- - name: Run tests
- shell: bash -l {0}
- run: |
- conda activate test-env
- pytest --cov pya/
+ - uses: actions/checkout@v5
+ - uses: astral-sh/setup-uv@v8.1.0
+ - name: Retrieve pre-built distribution files
+ uses: actions/download-artifact@v4
+ with: {name: python-distribution-files, path: dist/}
+ - name: Publish Package
+ env:
+ # TODO: Set your PYPI_TOKEN as a secret using GitHub UI
+ # - https://pypi.org/help/#apitoken
+ # - https://docs.github.com/en/actions/security-guides/encrypted-secrets
+ UV_PUBLISH_URL: https://upload.pypi.org/legacy/
+ UV_PUBLISH_USERNAME: __token__
+ UV_PUBLISH_PASSWORD: ${{ secrets.PYPI_TOKEN }}
+ run: uv run tox -e publish
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..76d97eb9
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,37 @@
+exclude: '^docs/conf.py|^uv\.lock$'
+
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.4.0
+ hooks:
+ - id: check-added-large-files
+ exclude: uv.lock
+ - id: check-ast
+ - id: check-json
+ - id: check-merge-conflict
+ - id: check-xml
+ - id: check-yaml
+ - id: end-of-file-fixer
+ exclude: "uv.lock"
+ - id: mixed-line-ending
+ exclude: "uv.lock"
+ args: ['--fix=auto'] # replace 'auto' with 'lf' to enforce Linux/Mac line endings or 'crlf' for Windows
+
+- repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.9.0 # check latest
+ hooks:
+ - id: ruff # replaces isort + flake8
+ args: [--fix] # auto-fix where possible
+ - id: ruff-format # replaces black
+
+- repo: https://github.com/kynan/nbstripout
+ rev: 0.8.1
+ hooks:
+ - id: nbstripout
+ args: [--extra-keys=metadata.kernelspec metadata.language_info]
+
+
+- repo: https://github.com/astral-sh/uv-pre-commit
+ rev: 0.6.0 # check latest
+ hooks:
+ - id: uv-lock # updates uv.lock when pyproject.toml changes
diff --git a/Changelog.md b/Changelog.md
index dd49c6a7..c2b263a6 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,12 @@
# Changelog
+## 0.6.0
+* changed project management and build system to use `uv`. Most of the configuration is now gathered in the `pyproject.toml`.
+* added pre-commit hooks and executed a lot of internal "form" refactoring to modern ruff standards (imports, documentation)
+* updated the github CI/CD pipelines to execute matrix testing for Ubuntu, MacOS and Windows
+
+
+
## 0.5.2 (Nov 2023)
* #82, `pyaudio` is now optional: If you plan to use `PyAudioBackend`, install `pya` with `pip install pya[pyaudio]`.
* Fix audio device bug
@@ -86,4 +93,3 @@
## 0.2 (August 2019)
* First official PyPI release
-
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 740025af..00000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,30 +0,0 @@
-include *.md
-include *.txt
-include *.yml
-include .coveragerc
-include .pylintrc
-include LICENSE
-include MANIFEST
-include tox.ini
-include binder/environment.yml
-include binder/postBuild
-include dev/generate_doc
-
-recursive-include docs Makefile
-recursive-include docs *.bat
-recursive-include docs *.html
-recursive-include docs *.py
-recursive-include docs *.rst
-
-recursive-include examples *.aif
-recursive-include examples *.ipynb
-recursive-include examples *.mp3
-recursive-include examples *.py
-recursive-include examples *.wav
-recursive-exclude examples .ipynb_checkpoints/*.ipynb
-
-recursive-include tests *.py
-recursive-include pya *.py
-recursive-include dev *.md
-recursive-include dev *.py
-recursive-include ci *.yml
diff --git a/README.md b/README.md
index 2374d45d..5ce717c6 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,13 @@
[](https://pypi.org/project/pya)
-[](LICENSE)
+[](../LICENSE)
# pya
-|Branch|`master`|`develop`|
+
+
+|Branch|`main`|`develop`|
|------:|--------:|---------:|
-|[CI-Linux/MacOS](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml) | [](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml?query=branch%3Amaster) | [](https://github.com/interactive-sonification/pya/actions/workflows/pya-ci.yaml?query=branch%3Adevelop) |
-|[CI-Windows](https://ci.appveyor.com/project/aleneum/pya-b7gkx/)|  |  |
|Changes|[](https://github.com/interactive-sonification/pya/compare/v0.5.0...master) | [](https://github.com/interactive-sonification/pya/compare/v0.5.0...develop) |
|Binder|[](https://mybinder.org/v2/gh/interactive-sonification/pya/master?filepath=examples%2Fpya-examples.ipynb) | [](https://mybinder.org/v2/gh/interactive-sonification/pya/develop?filepath=examples%2Fpya-examples.ipynb) |
@@ -40,9 +41,14 @@ At this time pya is more suitable for offline rendering than realtime.
## Authors and Contributors
-* [Thomas](https://github.com/thomas-hermann) (author, maintainer)
-* [Jiajun](https://github.com/wiccy46) (co-author, maintainer)
-* [Alexander](https://github.com/aleneum) (maintainer)
+* [Thomas Hermann](https://github.com/thomas-hermann) (author, maintainer)
+* [Jiajun Yang](https://github.com/wiccy46) (co-author, maintainer)
+* [Alexander Neumann](https://github.com/aleneum) (maintainer)
+
+* [Luka Born]() (Contributor)
+* [Jannis Müller]() (Contributor)
+* [Fabian Hommel]() (Maintainer)
+
* Contributors will be acknowledged here, contributions are welcome.
## Installation
@@ -269,4 +275,4 @@ ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
-```
\ No newline at end of file
+```
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index c6b94ef3..00000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-# no dedicated build phase needed so far
-build: false
-version: "0.3.2-{build}"
-
-branches:
- only:
- - master
- - develop
- - dev-appveyor
-
-environment:
- matrix:
- - PYTHON_VERSION: 3.10
- MINICONDA: C:\Miniconda3-x64
-
-init:
- - "ECHO %PYTHON_VERSION% %MINICONDA%"
-
-install:
- - "set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%MINICONDA%\\Library\\bin;%PATH%"
- - conda config --set always_yes yes --set changeps1 no
- - conda update -q conda
- - conda info -a
- - conda config --append channels conda-forge
- - "conda create -q -n test-environment python=%PYTHON_VERSION% ffmpeg coverage --file=requirements_remote.txt --file=requirements_test.txt"
- - activate test-environment
- - "pip install -r requirements.txt -r requirements_pyaudio.txt"
-
-test_script:
- - pytest
diff --git a/coverage.lcov b/coverage.lcov
new file mode 100644
index 00000000..19b76047
--- /dev/null
+++ b/coverage.lcov
@@ -0,0 +1,2632 @@
+SF:pya/__init__.py
+DA:1,1
+DA:2,1
+DA:3,1
+DA:4,1
+DA:5,1
+DA:6,1
+DA:9,1
+DA:10,1
+DA:11,1
+DA:12,1
+DA:14,1
+DA:17,1
+DA:18,0
+DA:21,1
+DA:22,0
+LF:15
+LH:13
+FN:17,18,startup
+FNDA:0,startup
+FN:21,22,shutdown
+FNDA:0,shutdown
+FNF:2
+FNH:0
+end_of_record
+SF:pya/amfcc.py
+DA:1,1
+DA:2,1
+DA:4,1
+DA:5,1
+DA:6,1
+DA:7,1
+DA:9,1
+DA:11,1
+DA:24,1
+DA:77,1
+DA:134,1
+DA:135,1
+DA:136,1
+DA:137,1
+DA:138,1
+DA:139,1
+DA:140,1
+DA:141,1
+DA:143,1
+DA:144,1
+DA:145,1
+DA:146,1
+DA:148,1
+DA:149,1
+DA:150,1
+DA:151,1
+DA:152,1
+DA:153,1
+DA:155,1
+DA:156,1
+DA:159,1
+DA:161,1
+DA:162,1
+DA:163,1
+DA:164,1
+DA:165,1
+DA:166,1
+DA:167,1
+DA:168,1
+DA:169,1
+DA:170,1
+DA:172,1
+DA:173,1
+DA:174,1
+DA:175,1
+DA:179,1
+DA:180,1
+DA:186,1
+DA:187,1
+DA:190,1
+DA:192,1
+DA:198,1
+DA:203,1
+DA:204,1
+DA:205,1
+DA:208,1
+DA:210,1
+DA:213,1
+DA:214,1
+DA:216,1
+DA:217,1
+DA:218,1
+DA:220,1
+DA:221,1
+DA:222,1
+DA:224,1
+DA:225,1
+DA:227,1
+DA:229,1
+DA:230,1
+DA:232,1
+DA:233,1
+DA:252,1
+DA:254,1
+DA:255,1
+DA:285,1
+DA:288,1
+DA:289,1
+DA:290,1
+DA:293,1
+DA:295,1
+DA:296,1
+DA:297,1
+DA:298,1
+DA:299,1
+DA:300,1
+DA:301,1
+DA:303,1
+DA:304,1
+DA:334,1
+DA:335,1
+DA:336,1
+DA:337,1
+DA:338,1
+DA:341,1
+DA:343,1
+DA:373,1
+DA:374,1
+DA:378,1
+DA:379,1
+DA:394,1
+DA:395,1
+DA:396,1
+DA:398,1
+DA:399,1
+DA:401,1
+DA:402,1
+DA:404,1
+LF:108
+LH:108
+FN:77,214,Amfcc.__init__
+FNDA:1,Amfcc.__init__
+FN:217,218,Amfcc.nframes
+FNDA:1,Amfcc.nframes
+FN:221,222,Amfcc.timestamp
+FNDA:1,Amfcc.timestamp
+FN:225,227,Amfcc.features
+FNDA:1,Amfcc.features
+FN:229,230,Amfcc.__repr__
+FNDA:1,Amfcc.__repr__
+FN:233,252,Amfcc.preemphasis
+FNDA:1,Amfcc.preemphasis
+FN:255,301,Amfcc.mel_filterbanks
+FNDA:1,Amfcc.mel_filterbanks
+FN:304,341,Amfcc.lifter
+FNDA:1,Amfcc.lifter
+FN:343,404,Amfcc.plot
+FNDA:1,Amfcc.plot
+FNF:9
+FNH:9
+end_of_record
+SF:pya/arecorder.py
+DA:2,1
+DA:3,1
+DA:4,1
+DA:5,1
+DA:7,1
+DA:8,1
+DA:10,1
+DA:11,1
+DA:13,1
+DA:14,1
+DA:17,1
+DA:38,1
+DA:47,1
+DA:48,1
+DA:49,1
+DA:50,1
+DA:51,1
+DA:52,1
+DA:53,1
+DA:58,1
+DA:59,1
+DA:61,1
+DA:62,1
+DA:63,1
+DA:65,1
+DA:66,1
+DA:70,0
+DA:71,0
+DA:72,0
+DA:74,1
+DA:86,0
+DA:87,0
+DA:88,0
+DA:89,0
+DA:90,0
+DA:91,0
+DA:92,0
+DA:93,0
+DA:94,0
+DA:95,0
+DA:97,0
+DA:99,1
+DA:100,0
+DA:101,0
+DA:103,1
+DA:104,1
+DA:105,1
+DA:107,1
+DA:108,1
+DA:109,1
+DA:118,1
+DA:119,1
+DA:121,1
+DA:124,0
+DA:125,0
+DA:127,0
+DA:128,0
+DA:132,0
+DA:135,0
+DA:137,1
+DA:139,1
+DA:141,1
+DA:143,0
+DA:145,1
+DA:147,1
+DA:148,1
+DA:149,1
+DA:150,1
+DA:151,1
+DA:153,0
+DA:155,1
+DA:156,0
+DA:157,0
+DA:158,0
+DA:159,0
+DA:162,0
+LF:76
+LH:47
+FN:38,59,Arecorder.__init__
+FNDA:1,Arecorder.__init__
+FN:62,63,Arecorder.channels
+FNDA:1,Arecorder.channels
+FN:66,72,Arecorder.channels
+FNDA:0,Arecorder.channels
+FN:74,97,Arecorder.set_tracks
+FNDA:0,Arecorder.set_tracks
+FN:99,101,Arecorder.reset
+FNDA:0,Arecorder.reset
+FN:103,119,Arecorder.boot
+FNDA:1,Arecorder.boot
+FN:121,135,Arecorder._recorder_callback
+FNDA:0,Arecorder._recorder_callback
+FN:137,139,Arecorder.record
+FNDA:1,Arecorder.record
+FN:141,143,Arecorder.pause
+FNDA:0,Arecorder.pause
+FN:145,153,Arecorder.stop
+FNDA:1,Arecorder.stop
+FN:155,162,Arecorder.__repr__
+FNDA:0,Arecorder.__repr__
+FNF:11
+FNH:5
+end_of_record
+SF:pya/aserver.py
+DA:1,1
+DA:2,1
+DA:3,1
+DA:4,1
+DA:5,1
+DA:7,1
+DA:9,1
+DA:11,1
+DA:12,1
+DA:15,1
+DA:35,1
+DA:37,1
+DA:38,1
+DA:39,1
+DA:40,1
+DA:41,1
+DA:42,1
+DA:43,1
+DA:45,0
+DA:46,1
+DA:48,1
+DA:49,1
+DA:50,1
+DA:51,1
+DA:52,1
+DA:53,1
+DA:55,0
+DA:57,1
+DA:88,1
+DA:89,1
+DA:90,1
+DA:91,1
+DA:93,1
+DA:94,1
+DA:95,1
+DA:96,1
+DA:97,1
+DA:98,1
+DA:99,1
+DA:101,1
+DA:106,1
+DA:108,1
+DA:109,1
+DA:110,1
+DA:111,1
+DA:112,1
+DA:113,1
+DA:114,1
+DA:115,1
+DA:116,1
+DA:117,1
+DA:118,1
+DA:119,1
+DA:121,1
+DA:122,1
+DA:123,1
+DA:125,1
+DA:126,1
+DA:130,0
+DA:131,0
+DA:132,0
+DA:134,1
+DA:135,1
+DA:136,1
+DA:138,1
+DA:139,1
+DA:140,1
+DA:142,1
+DA:143,1
+DA:144,1
+DA:146,1
+DA:147,1
+DA:148,1
+DA:150,1
+DA:151,1
+DA:152,1
+DA:154,1
+DA:155,1
+DA:156,0
+DA:161,0
+DA:162,0
+DA:165,0
+DA:167,1
+DA:168,1
+DA:172,1
+DA:174,1
+DA:176,1
+DA:177,1
+DA:178,1
+DA:184,1
+DA:185,1
+DA:191,1
+DA:193,1
+DA:205,0
+DA:206,0
+DA:207,0
+DA:208,0
+DA:209,0
+DA:210,0
+DA:211,0
+DA:212,0
+DA:213,0
+DA:214,0
+DA:216,1
+DA:218,1
+DA:219,1
+DA:220,1
+DA:221,1
+DA:222,1
+DA:223,1
+DA:224,1
+DA:233,1
+DA:234,1
+DA:235,1
+DA:237,1
+DA:239,1
+DA:240,1
+DA:241,1
+DA:242,1
+DA:243,1
+DA:244,1
+DA:245,1
+DA:246,1
+DA:247,0
+DA:248,0
+DA:249,1
+DA:251,1
+DA:261,1
+DA:263,1
+DA:264,1
+DA:265,0
+DA:266,1
+DA:267,1
+DA:269,0
+DA:270,1
+DA:271,1
+DA:272,1
+DA:273,0
+DA:274,0
+DA:275,0
+DA:276,0
+DA:278,1
+DA:282,1
+DA:283,1
+DA:284,1
+DA:285,1
+DA:286,1
+DA:289,1
+DA:290,1
+DA:291,1
+DA:292,1
+DA:293,1
+DA:294,0
+DA:296,1
+DA:297,1
+DA:299,1
+DA:301,1
+DA:302,1
+DA:305,1
+DA:306,1
+DA:307,1
+DA:308,1
+DA:309,1
+DA:311,1
+DA:312,1
+DA:313,1
+DA:314,0
+DA:315,0
+DA:316,0
+DA:317,0
+DA:318,0
+DA:319,1
+DA:321,1
+DA:322,1
+DA:323,1
+DA:324,1
+DA:325,1
+DA:326,1
+DA:327,1
+DA:328,1
+DA:329,1
+DA:331,1
+DA:332,1
+DA:333,1
+DA:334,1
+DA:336,1
+DA:337,1
+DA:338,1
+DA:339,0
+DA:341,1
+DA:342,0
+DA:343,0
+DA:344,0
+DA:345,0
+DA:346,1
+DA:348,1
+DA:349,1
+DA:351,1
+DA:352,1
+DA:354,1
+DA:356,1
+DA:357,1
+DA:358,1
+DA:360,1
+DA:362,1
+DA:363,0
+DA:364,0
+DA:365,0
+DA:366,0
+DA:367,0
+LF:210
+LH:167
+FN:38,46,Aserver.startup_default_server
+FNDA:1,Aserver.startup_default_server
+FN:49,55,Aserver.shutdown_default_server
+FNDA:1,Aserver.shutdown_default_server
+FN:57,119,Aserver.__init__
+FNDA:1,Aserver.__init__
+FN:122,123,Aserver.channels
+FNDA:1,Aserver.channels
+FN:126,132,Aserver.channels
+FNDA:0,Aserver.channels
+FN:135,136,Aserver.device_dict
+FNDA:1,Aserver.device_dict
+FN:139,140,Aserver.max_out_chn
+FNDA:1,Aserver.max_out_chn
+FN:143,144,Aserver.max_in_chn
+FNDA:1,Aserver.max_in_chn
+FN:147,148,Aserver.is_active
+FNDA:1,Aserver.is_active
+FN:151,152,Aserver.device
+FNDA:1,Aserver.device
+FN:155,165,Aserver.device
+FNDA:0,Aserver.device
+FN:167,172,Aserver.__repr__
+FNDA:1,Aserver.__repr__
+FN:174,191,Aserver.get_devices
+FNDA:1,Aserver.get_devices
+FN:193,214,Aserver.set_device
+FNDA:0,Aserver.set_device
+FN:216,235,Aserver.boot
+FNDA:1,Aserver.boot
+FN:237,249,Aserver.quit
+FNDA:1,Aserver.quit
+FN:251,297,Aserver.play
+FNDA:1,Aserver.play
+FN:299,346,Aserver._play_callback
+FNDA:1,Aserver._play_callback
+FN:348,349,Aserver.stop
+FNDA:1,Aserver.stop
+FN:351,352,Aserver.__enter__
+FNDA:1,Aserver.__enter__
+FN:354,358,Aserver.__exit__
+FNDA:1,Aserver.__exit__
+FN:360,367,Aserver.__del__
+FNDA:1,Aserver.__del__
+FNF:22
+FNH:19
+end_of_record
+SF:pya/asig.py
+DA:1,1
+DA:2,1
+DA:3,1
+DA:4,1
+DA:5,1
+DA:7,1
+DA:8,1
+DA:9,1
+DA:10,1
+DA:11,1
+DA:12,1
+DA:14,1
+DA:16,1
+DA:17,1
+DA:20,1
+DA:54,1
+DA:92,1
+DA:93,1
+DA:95,0
+DA:96,1
+DA:97,1
+DA:98,1
+DA:99,1
+DA:100,1
+DA:101,0
+DA:102,0
+DA:103,0
+DA:104,1
+DA:105,1
+DA:106,1
+DA:108,1
+DA:109,1
+DA:110,1
+DA:111,1
+DA:113,1
+DA:115,1
+DA:116,1
+DA:117,1
+DA:118,1
+DA:119,0
+DA:122,1
+DA:124,1
+DA:125,1
+DA:127,1
+DA:128,1
+DA:129,1
+DA:130,1
+DA:132,1
+DA:133,1
+DA:135,1
+DA:137,1
+DA:138,1
+DA:140,1
+DA:141,1
+DA:143,1
+DA:145,1
+DA:146,1
+DA:148,1
+DA:150,1
+DA:154,1
+DA:155,1
+DA:159,1
+DA:161,1
+DA:162,1
+DA:166,1
+DA:168,1
+DA:179,1
+DA:180,1
+DA:181,1
+DA:182,0
+DA:183,1
+DA:184,1
+DA:185,1
+DA:186,1
+DA:187,1
+DA:188,1
+DA:190,1
+DA:191,1
+DA:192,1
+DA:194,1
+DA:195,1
+DA:197,0
+DA:199,1
+DA:226,1
+DA:227,1
+DA:228,1
+DA:229,1
+DA:230,1
+DA:231,0
+DA:234,0
+DA:237,1
+DA:238,1
+DA:242,1
+DA:243,1
+DA:244,1
+DA:245,1
+DA:246,1
+DA:247,1
+DA:248,1
+DA:249,1
+DA:250,1
+DA:251,1
+DA:252,1
+DA:253,1
+DA:254,1
+DA:255,1
+DA:256,1
+DA:257,1
+DA:258,1
+DA:259,1
+DA:260,0
+DA:261,0
+DA:262,1
+DA:263,1
+DA:264,1
+DA:265,1
+DA:266,1
+DA:267,1
+DA:268,1
+DA:270,1
+DA:271,1
+DA:274,1
+DA:275,1
+DA:276,1
+DA:277,1
+DA:278,1
+DA:279,0
+DA:280,1
+DA:281,1
+DA:282,1
+DA:283,1
+DA:285,1
+DA:286,1
+DA:287,1
+DA:290,0
+DA:291,0
+DA:292,0
+DA:293,1
+DA:294,1
+DA:295,1
+DA:296,1
+DA:297,1
+DA:298,1
+DA:299,1
+DA:300,1
+DA:302,1
+DA:303,0
+DA:304,0
+DA:305,0
+DA:307,1
+DA:308,1
+DA:310,1
+DA:316,1
+DA:318,1
+DA:319,1
+DA:320,1
+DA:321,1
+DA:322,1
+DA:323,1
+DA:325,1
+DA:326,1
+DA:327,1
+DA:329,1
+DA:330,1
+DA:336,1
+DA:337,1
+DA:339,1
+DA:341,1
+DA:342,1
+DA:348,1
+DA:349,1
+DA:351,1
+DA:353,1
+DA:354,1
+DA:359,1
+DA:360,1
+DA:362,1
+DA:364,1
+DA:410,1
+DA:411,1
+DA:413,1
+DA:414,1
+DA:415,1
+DA:417,1
+DA:418,1
+DA:420,1
+DA:421,1
+DA:422,1
+DA:424,1
+DA:425,1
+DA:426,1
+DA:427,0
+DA:428,0
+DA:429,1
+DA:430,1
+DA:431,1
+DA:432,1
+DA:433,1
+DA:434,1
+DA:435,1
+DA:437,1
+DA:440,1
+DA:441,1
+DA:442,1
+DA:443,1
+DA:445,0
+DA:446,0
+DA:447,0
+DA:448,0
+DA:450,1
+DA:451,1
+DA:453,1
+DA:454,0
+DA:456,1
+DA:458,1
+DA:459,1
+DA:460,1
+DA:462,1
+DA:465,1
+DA:466,1
+DA:467,1
+DA:469,1
+DA:471,1
+DA:472,1
+DA:474,1
+DA:475,1
+DA:476,1
+DA:478,1
+DA:481,1
+DA:482,1
+DA:483,1
+DA:485,1
+DA:486,1
+DA:487,1
+DA:488,1
+DA:489,1
+DA:492,1
+DA:494,1
+DA:495,1
+DA:498,0
+DA:499,0
+DA:501,1
+DA:502,1
+DA:503,1
+DA:504,1
+DA:505,1
+DA:506,1
+DA:507,1
+DA:509,1
+DA:511,1
+DA:512,1
+DA:513,1
+DA:514,0
+DA:515,0
+DA:516,1
+DA:517,1
+DA:518,0
+DA:519,1
+DA:520,0
+DA:523,1
+DA:525,1
+DA:526,1
+DA:527,1
+DA:528,1
+DA:529,1
+DA:530,1
+DA:532,1
+DA:533,1
+DA:535,1
+DA:538,1
+DA:539,0
+DA:541,1
+DA:543,1
+DA:544,1
+DA:548,1
+DA:549,1
+DA:551,1
+DA:553,1
+DA:556,1
+DA:557,1
+DA:560,1
+DA:563,1
+DA:566,1
+DA:572,1
+DA:573,1
+DA:574,1
+DA:575,0
+DA:576,1
+DA:578,1
+DA:580,1
+DA:581,1
+DA:582,1
+DA:584,1
+DA:602,1
+DA:603,1
+DA:608,1
+DA:609,1
+DA:617,1
+DA:621,0
+DA:624,0
+DA:625,0
+DA:633,0
+DA:634,0
+DA:636,1
+DA:655,1
+DA:657,1
+DA:658,1
+DA:659,1
+DA:660,1
+DA:662,0
+DA:663,1
+DA:664,1
+DA:666,1
+DA:687,1
+DA:688,0
+DA:690,1
+DA:691,1
+DA:694,1
+DA:695,1
+DA:696,0
+DA:697,0
+DA:698,0
+DA:699,0
+DA:700,1
+DA:701,0
+DA:703,1
+DA:704,1
+DA:705,1
+DA:706,1
+DA:708,0
+DA:709,0
+DA:710,0
+DA:711,1
+DA:713,1
+DA:729,1
+DA:730,1
+DA:731,1
+DA:732,1
+DA:733,0
+DA:734,1
+DA:735,0
+DA:737,1
+DA:738,1
+DA:739,1
+DA:741,1
+DA:775,1
+DA:776,1
+DA:777,1
+DA:779,1
+DA:780,1
+DA:782,1
+DA:783,1
+DA:784,1
+DA:785,1
+DA:786,1
+DA:787,1
+DA:789,1
+DA:790,1
+DA:791,1
+DA:793,0
+DA:797,0
+DA:799,1
+DA:800,1
+DA:802,1
+DA:822,1
+DA:823,1
+DA:824,0
+DA:825,0
+DA:827,1
+DA:828,1
+DA:829,1
+DA:830,1
+DA:832,1
+DA:851,1
+DA:853,1
+DA:854,1
+DA:855,1
+DA:856,1
+DA:858,1
+DA:859,1
+DA:860,1
+DA:861,1
+DA:869,1
+DA:876,1
+DA:878,1
+DA:880,1
+DA:892,1
+DA:893,1
+DA:895,1
+DA:914,1
+DA:915,1
+DA:916,1
+DA:917,1
+DA:919,1
+DA:920,1
+DA:921,1
+DA:923,1
+DA:942,1
+DA:943,1
+DA:944,1
+DA:945,1
+DA:946,1
+DA:947,1
+DA:948,1
+DA:950,1
+DA:958,1
+DA:960,1
+DA:993,1
+DA:994,1
+DA:996,1
+DA:997,1
+DA:999,1
+DA:1000,1
+DA:1001,1
+DA:1002,1
+DA:1004,1
+DA:1005,1
+DA:1011,1
+DA:1024,1
+DA:1026,1
+DA:1028,1
+DA:1030,1
+DA:1032,1
+DA:1034,1
+DA:1039,1
+DA:1040,1
+DA:1041,1
+DA:1043,1
+DA:1045,1
+DA:1054,1
+DA:1063,1
+DA:1064,1
+DA:1065,1
+DA:1066,1
+DA:1073,1
+DA:1074,1
+DA:1075,0
+DA:1076,1
+DA:1077,1
+DA:1078,1
+DA:1079,1
+DA:1080,1
+DA:1081,1
+DA:1082,0
+DA:1083,0
+DA:1085,1
+DA:1086,1
+DA:1087,1
+DA:1089,0
+DA:1091,1
+DA:1092,1
+DA:1094,1
+DA:1095,1
+DA:1099,1
+DA:1110,1
+DA:1111,1
+DA:1112,1
+DA:1113,1
+DA:1120,0
+DA:1121,0
+DA:1122,0
+DA:1123,0
+DA:1124,0
+DA:1125,0
+DA:1126,0
+DA:1127,0
+DA:1128,0
+DA:1129,0
+DA:1130,0
+DA:1132,0
+DA:1134,0
+DA:1135,0
+DA:1136,0
+DA:1138,0
+DA:1140,0
+DA:1141,0
+DA:1143,1
+DA:1144,1
+DA:1148,1
+DA:1156,1
+DA:1157,1
+DA:1158,1
+DA:1159,1
+DA:1163,1
+DA:1164,1
+DA:1165,1
+DA:1166,1
+DA:1167,1
+DA:1168,1
+DA:1169,0
+DA:1170,0
+DA:1171,1
+DA:1172,1
+DA:1173,1
+DA:1175,1
+DA:1176,0
+DA:1177,0
+DA:1179,1
+DA:1180,1
+DA:1181,1
+DA:1183,1
+DA:1185,1
+DA:1186,1
+DA:1188,1
+DA:1189,0
+DA:1191,1
+DA:1199,1
+DA:1200,1
+DA:1201,1
+DA:1202,1
+DA:1209,1
+DA:1210,1
+DA:1211,1
+DA:1212,0
+DA:1213,1
+DA:1214,1
+DA:1215,0
+DA:1216,0
+DA:1217,1
+DA:1218,1
+DA:1219,1
+DA:1221,1
+DA:1222,0
+DA:1223,0
+DA:1225,1
+DA:1227,1
+DA:1228,1
+DA:1229,1
+DA:1231,0
+DA:1233,1
+DA:1234,1
+DA:1236,1
+DA:1237,1
+DA:1241,1
+DA:1275,1
+DA:1276,0
+DA:1279,0
+DA:1280,0
+DA:1281,1
+DA:1282,1
+DA:1283,1
+DA:1284,1
+DA:1285,1
+DA:1286,1
+DA:1287,1
+DA:1288,1
+DA:1290,0
+DA:1291,1
+DA:1292,1
+DA:1293,1
+DA:1294,1
+DA:1295,1
+DA:1296,1
+DA:1297,1
+DA:1298,1
+DA:1299,1
+DA:1301,1
+DA:1302,1
+DA:1303,1
+DA:1305,1
+DA:1306,1
+DA:1308,1
+DA:1309,1
+DA:1317,1
+DA:1318,1
+DA:1319,1
+DA:1321,1
+DA:1336,0
+DA:1337,0
+DA:1338,0
+DA:1339,0
+DA:1340,0
+DA:1341,0
+DA:1342,0
+DA:1343,0
+DA:1344,0
+DA:1350,0
+DA:1351,0
+DA:1353,1
+DA:1354,0
+DA:1355,0
+DA:1356,0
+DA:1357,0
+DA:1358,0
+DA:1359,0
+DA:1360,0
+DA:1362,1
+DA:1377,1
+DA:1378,1
+DA:1379,0
+DA:1380,0
+DA:1383,1
+DA:1384,1
+DA:1385,1
+DA:1392,0
+DA:1395,0
+DA:1402,1
+DA:1417,1
+DA:1418,1
+DA:1419,0
+DA:1420,0
+DA:1423,1
+DA:1424,1
+DA:1425,1
+DA:1432,0
+DA:1435,0
+DA:1442,1
+DA:1486,0
+DA:1487,0
+DA:1488,0
+DA:1489,0
+DA:1490,0
+DA:1491,0
+DA:1492,0
+DA:1493,0
+DA:1495,1
+DA:1512,0
+DA:1513,0
+DA:1515,1
+DA:1536,0
+DA:1537,0
+DA:1538,0
+DA:1539,0
+DA:1541,0
+DA:1542,0
+DA:1544,0
+DA:1545,0
+DA:1546,0
+DA:1547,0
+DA:1550,0
+DA:1553,0
+DA:1554,0
+DA:1555,0
+DA:1556,0
+DA:1557,0
+DA:1559,0
+DA:1560,0
+DA:1561,0
+DA:1562,0
+DA:1563,0
+DA:1567,0
+DA:1569,1
+DA:1601,0
+DA:1602,0
+DA:1609,1
+DA:1626,1
+DA:1627,0
+DA:1628,1
+DA:1629,1
+DA:1630,0
+DA:1631,1
+DA:1632,1
+DA:1639,1
+DA:1640,1
+DA:1641,1
+DA:1643,1
+DA:1663,1
+DA:1664,1
+DA:1667,1
+DA:1672,1
+DA:1673,1
+DA:1674,1
+DA:1675,1
+DA:1676,1
+DA:1677,1
+DA:1678,1
+DA:1679,1
+DA:1680,1
+DA:1681,1
+DA:1683,0
+DA:1685,1
+DA:1686,1
+DA:1688,0
+DA:1689,1
+DA:1693,1
+DA:1729,0
+DA:1735,0
+DA:1736,0
+DA:1737,0
+DA:1738,0
+DA:1739,0
+DA:1740,0
+DA:1741,0
+DA:1742,0
+DA:1743,0
+DA:1744,0
+DA:1745,0
+DA:1746,0
+DA:1747,0
+DA:1748,0
+DA:1749,0
+DA:1750,0
+DA:1751,0
+DA:1752,0
+DA:1754,1
+DA:1756,1
+DA:1758,1
+DA:1760,1
+DA:1766,1
+DA:1768,1
+DA:1770,1
+DA:1783,1
+DA:1785,1
+DA:1800,1
+DA:1826,0
+DA:1827,0
+DA:1828,0
+DA:1829,0
+DA:1830,0
+DA:1831,0
+DA:1832,0
+DA:1833,0
+DA:1834,0
+DA:1835,0
+DA:1839,0
+DA:1840,0
+DA:1841,0
+DA:1842,0
+DA:1844,0
+DA:1849,0
+DA:1850,0
+DA:1851,0
+DA:1852,0
+DA:1853,0
+DA:1854,0
+DA:1855,0
+DA:1856,0
+DA:1857,0
+DA:1865,0
+DA:1866,0
+DA:1867,0
+DA:1868,0
+DA:1869,0
+DA:1871,1
+DA:1876,0
+DA:1877,0
+DA:1879,1
+DA:1881,0
+DA:1883,1
+DA:1901,1
+DA:1902,1
+DA:1903,1
+DA:1904,0
+DA:1905,0
+DA:1907,1
+DA:1908,1
+DA:1909,1
+DA:1911,1
+DA:1912,1
+DA:1919,1
+DA:1940,0
+DA:1941,0
+DA:1942,0
+DA:1943,0
+DA:1944,0
+DA:1945,0
+DA:1946,0
+DA:1947,0
+DA:1952,0
+DA:1953,0
+DA:1954,0
+DA:1955,0
+DA:1956,0
+DA:1957,0
+DA:1958,0
+DA:1959,0
+DA:1960,0
+DA:1961,0
+DA:1962,0
+DA:1963,0
+DA:1964,0
+DA:1966,1
+DA:1968,0
+DA:1976,1
+DA:1995,0
+DA:2003,1
+DA:2005,0
+DA:2006,0
+DA:2008,1
+DA:2048,1
+DA:2049,1
+DA:2050,0
+DA:2051,0
+DA:2052,1
+DA:2053,1
+DA:2054,1
+DA:2055,1
+DA:2056,1
+DA:2057,1
+DA:2058,1
+DA:2060,1
+DA:2062,1
+DA:2064,0
+DA:2067,1
+DA:2070,1
+DA:2072,1
+DA:2076,1
+DA:2077,0
+DA:2082,1
+DA:2083,1
+DA:2084,1
+DA:2085,1
+DA:2086,1
+DA:2087,1
+DA:2088,1
+DA:2090,1
+DA:2091,1
+DA:2094,1
+DA:2098,1
+DA:2111,0
+DA:2112,0
+DA:2113,0
+LF:812
+LH:572
+FN:54,122,Asig.__init__
+FNDA:1,Asig.__init__
+FN:125,130,Asig.channels
+FNDA:1,Asig.channels
+FN:133,135,Asig.cn
+FNDA:1,Asig.cn
+FN:138,152,Asig.cn
+FNDA:1,Asig.cn
+FN:155,159,Asig.samples
+FNDA:1,Asig.samples
+FN:162,166,Asig.dur
+FNDA:1,Asig.dur
+FN:168,188,Asig.save_wavfile
+FNDA:1,Asig.save_wavfile
+FN:190,197,Asig._set_col_names
+FNDA:1,Asig._set_col_names
+FN:199,327,Asig.__getitem__
+FNDA:1,Asig.__getitem__
+FN:330,337,Asig.x
+FNDA:1,Asig.x
+FN:342,349,Asig.b
+FNDA:1,Asig.b
+FN:354,360,Asig.o
+FNDA:1,Asig.o
+FN:364,582,Asig.__setitem__
+FNDA:1,Asig.__setitem__
+FN:584,634,Asig.resample
+FNDA:1,Asig.resample
+FN:636,664,Asig.play
+FNDA:1,Asig.play
+FN:666,711,Asig.shift_channel
+FNDA:1,Asig.shift_channel
+FN:713,739,Asig.mono
+FNDA:1,Asig.mono
+FN:741,800,Asig.stereo
+FNDA:1,Asig.stereo
+FN:802,830,Asig.rewire
+FNDA:1,Asig.rewire
+FN:832,878,Asig.pan2
+FNDA:1,Asig.pan2
+FN:880,893,Asig.remove_DC
+FNDA:1,Asig.remove_DC
+FN:895,921,Asig.norm
+FNDA:1,Asig.norm
+FN:923,948,Asig.gain
+FNDA:1,Asig.gain
+FN:950,958,Asig.rms
+FNDA:1,Asig.rms
+FN:960,1024,Asig.plot
+FNDA:1,Asig.plot
+FN:996,997,Asig.plot.fn
+FNDA:1,Asig.plot.fn
+FN:1026,1028,Asig.get_duration
+FNDA:1,Asig.get_duration
+FN:1030,1032,Asig.get_times
+FNDA:1,Asig.get_times
+FN:1034,1041,Asig.__eq__
+FNDA:1,Asig.__eq__
+FN:1043,1052,Asig.__repr__
+FNDA:1,Asig.__repr__
+FN:1054,1092,Asig.__mul__
+FNDA:1,Asig.__mul__
+FN:1094,1097,Asig.__rmul__
+FNDA:1,Asig.__rmul__
+FN:1099,1141,Asig.__truediv__
+FNDA:1,Asig.__truediv__
+FN:1143,1146,Asig.__rtruediv__
+FNDA:1,Asig.__rtruediv__
+FN:1148,1186,Asig.__add__
+FNDA:1,Asig.__add__
+FN:1188,1189,Asig.__radd__
+FNDA:0,Asig.__radd__
+FN:1191,1234,Asig.__sub__
+FNDA:1,Asig.__sub__
+FN:1236,1239,Asig.__rsub__
+FNDA:1,Asig.__rsub__
+FN:1241,1319,Asig.find_events
+FNDA:1,Asig.find_events
+FN:1321,1351,Asig.select_event
+FNDA:0,Asig.select_event
+FN:1353,1360,Asig.plot_events
+FNDA:0,Asig.plot_events
+FN:1362,1400,Asig.fade_in
+FNDA:1,Asig.fade_in
+FN:1402,1440,Asig.fade_out
+FNDA:1,Asig.fade_out
+FN:1442,1493,Asig.iirfilter
+FNDA:0,Asig.iirfilter
+FN:1495,1513,Asig.plot_freqz
+FNDA:0,Asig.plot_freqz
+FN:1515,1567,Asig.envelope
+FNDA:0,Asig.envelope
+FN:1569,1607,Asig.adsr
+FNDA:0,Asig.adsr
+FN:1609,1641,Asig.window
+FNDA:1,Asig.window
+FN:1643,1691,Asig.window_op
+FNDA:1,Asig.window_op
+FN:1693,1752,Asig.overlap_add
+FNDA:0,Asig.overlap_add
+FN:1754,1758,Asig.to_spec
+FNDA:1,Asig.to_spec
+FN:1760,1768,Asig.to_stft
+FNDA:1,Asig.to_stft
+FN:1770,1798,Asig.to_mfcc
+FNDA:1,Asig.to_mfcc
+FN:1800,1869,Asig.plot_spectrum
+FNDA:0,Asig.plot_spectrum
+FN:1871,1877,Asig.spectrogram
+FNDA:0,Asig.spectrogram
+FN:1879,1881,Asig.get_size
+FNDA:0,Asig.get_size
+FN:1883,1917,Asig.append
+FNDA:1,Asig.append
+FN:1919,1964,Asig.add
+FNDA:0,Asig.add
+FN:1966,1974,Asig.flatten
+FNDA:0,Asig.flatten
+FN:1976,2001,Asig.pad
+FNDA:0,Asig.pad
+FN:2003,2006,Asig.custom
+FNDA:0,Asig.custom
+FN:2008,2096,Asig.convolve
+FNDA:1,Asig.convolve
+FN:2098,2115,Asig.apply
+FNDA:0,Asig.apply
+FNF:63
+FNH:47
+end_of_record
+SF:pya/aspec.py
+DA:1,1
+DA:2,1
+DA:4,1
+DA:5,1
+DA:7,1
+DA:9,1
+DA:11,1
+DA:12,1
+DA:15,1
+DA:18,1
+DA:37,1
+DA:38,1
+DA:39,1
+DA:40,1
+DA:41,1
+DA:42,1
+DA:43,1
+DA:44,1
+DA:47,1
+DA:48,1
+DA:49,1
+DA:50,1
+DA:52,1
+DA:53,1
+DA:54,1
+DA:55,1
+DA:56,1
+DA:57,1
+DA:58,1
+DA:59,1
+DA:61,1
+DA:63,0
+DA:65,1
+DA:67,1
+DA:74,1
+DA:92,0
+DA:93,0
+DA:94,0
+DA:96,0
+DA:97,0
+DA:99,0
+DA:100,0
+DA:102,0
+DA:103,0
+DA:104,0
+DA:105,0
+DA:106,0
+DA:107,0
+DA:108,0
+DA:109,0
+DA:110,0
+DA:112,0
+DA:114,0
+DA:115,0
+DA:117,1
+DA:144,1
+DA:159,1
+DA:161,1
+DA:162,1
+LF:59
+LH:39
+FN:18,59,Aspec.__init__
+FNDA:1,Aspec.__init__
+FN:61,63,Aspec.get_duration
+FNDA:0,Aspec.get_duration
+FN:65,72,Aspec.to_sig
+FNDA:1,Aspec.to_sig
+FN:74,115,Aspec.weight
+FNDA:0,Aspec.weight
+FN:117,159,Aspec.plot
+FNDA:1,Aspec.plot
+FN:161,164,Aspec.__repr__
+FNDA:1,Aspec.__repr__
+FNF:6
+FNH:4
+end_of_record
+SF:pya/astft.py
+DA:1,1
+DA:3,1
+DA:4,1
+DA:6,1
+DA:7,1
+DA:9,1
+DA:11,1
+DA:13,1
+DA:14,1
+DA:18,1
+DA:24,1
+DA:92,1
+DA:93,1
+DA:94,1
+DA:95,1
+DA:96,1
+DA:97,1
+DA:98,1
+DA:99,1
+DA:101,1
+DA:103,1
+DA:104,1
+DA:105,1
+DA:106,1
+DA:107,1
+DA:108,1
+DA:109,1
+DA:110,1
+DA:111,1
+DA:113,1
+DA:115,1
+DA:116,1
+DA:117,1
+DA:118,1
+DA:119,1
+DA:120,0
+DA:125,1
+DA:126,1
+DA:129,1
+DA:133,1
+DA:147,1
+DA:148,0
+DA:149,0
+DA:151,0
+DA:153,1
+DA:170,1
+DA:179,1
+DA:180,0
+DA:181,1
+DA:182,0
+DA:183,0
+DA:184,1
+DA:186,1
+DA:187,1
+DA:191,0
+DA:192,0
+DA:196,1
+DA:229,1
+DA:244,1
+DA:245,1
+DA:247,1
+DA:248,1
+LF:62
+LH:53
+FN:24,151,Astft.__init__
+FNDA:1,Astft.__init__
+FN:153,194,Astft.to_sig
+FNDA:1,Astft.to_sig
+FN:196,245,Astft.plot
+FNDA:1,Astft.plot
+FN:247,255,Astft.__repr__
+FNDA:1,Astft.__repr__
+FNF:4
+FNH:4
+end_of_record
+SF:pya/backend/Dummy.py
+DA:1,1
+DA:2,1
+DA:4,1
+DA:6,1
+DA:8,1
+DA:11,1
+DA:12,1
+DA:13,1
+DA:14,1
+DA:16,1
+DA:17,1
+DA:21,1
+DA:22,1
+DA:24,1
+DA:25,1
+DA:27,1
+DA:28,0
+DA:30,1
+DA:31,1
+DA:33,1
+DA:44,1
+DA:45,1
+DA:46,1
+DA:47,1
+DA:55,1
+DA:56,1
+DA:58,1
+DA:59,1
+DA:61,1
+DA:62,1
+DA:65,1
+DA:66,1
+DA:75,1
+DA:76,1
+DA:77,1
+DA:78,1
+DA:79,1
+DA:80,1
+DA:81,1
+DA:82,1
+DA:83,1
+DA:84,1
+DA:86,1
+DA:87,1
+DA:88,1
+DA:91,1
+DA:93,1
+DA:94,1
+DA:96,1
+DA:97,0
+DA:98,0
+DA:101,0
+DA:102,0
+DA:104,1
+DA:105,1
+DA:106,1
+DA:107,1
+DA:108,1
+DA:109,1
+DA:111,1
+DA:112,1
+DA:113,1
+DA:114,0
+DA:115,0
+DA:116,0
+DA:117,1
+DA:118,1
+DA:119,1
+DA:120,1
+DA:122,1
+DA:123,1
+LF:71
+LH:63
+FN:16,19,DummyBackend.__init__
+FNDA:1,DummyBackend.__init__
+FN:21,22,DummyBackend.get_device_count
+FNDA:1,DummyBackend.get_device_count
+FN:24,25,DummyBackend.get_device_info_by_index
+FNDA:1,DummyBackend.get_device_info_by_index
+FN:27,28,DummyBackend.get_default_input_device_info
+FNDA:0,DummyBackend.get_default_input_device_info
+FN:30,31,DummyBackend.get_default_output_device_info
+FNDA:1,DummyBackend.get_default_output_device_info
+FN:33,56,DummyBackend.open
+FNDA:1,DummyBackend.open
+FN:58,59,DummyBackend.process_buffer
+FNDA:1,DummyBackend.process_buffer
+FN:61,62,DummyBackend.terminate
+FNDA:1,DummyBackend.terminate
+FN:66,84,DummyStream.__init__
+FNDA:1,DummyStream.__init__
+FN:86,91,DummyStream.stop_stream
+FNDA:1,DummyStream.stop_stream
+FN:93,94,DummyStream.close
+FNDA:1,DummyStream.close
+FN:96,102,DummyStream._generate_data
+FNDA:0,DummyStream._generate_data
+FN:104,109,DummyStream._process_data
+FNDA:1,DummyStream._process_data
+FN:111,120,DummyStream.start_stream
+FNDA:1,DummyStream.start_stream
+FN:122,123,DummyStream.is_active
+FNDA:1,DummyStream.is_active
+FNF:15
+FNH:13
+end_of_record
+SF:pya/backend/Jupyter.py
+DA:1,1
+DA:2,1
+DA:4,1
+DA:6,0
+DA:8,0
+DA:9,0
+DA:10,0
+DA:11,0
+DA:13,0
+DA:16,0
+DA:17,0
+DA:18,0
+DA:19,0
+DA:21,0
+DA:22,0
+DA:23,0
+DA:28,0
+DA:33,0
+DA:34,0
+DA:35,0
+DA:36,0
+DA:38,0
+DA:39,0
+DA:41,0
+DA:42,0
+DA:44,0
+DA:45,0
+DA:47,0
+DA:48,0
+DA:50,0
+DA:51,0
+DA:58,0
+DA:65,0
+DA:66,0
+DA:68,0
+DA:69,0
+DA:71,0
+DA:72,0
+DA:75,0
+DA:76,0
+DA:77,0
+DA:78,0
+DA:79,0
+DA:80,0
+DA:81,0
+DA:83,0
+DA:84,0
+DA:85,0
+DA:87,0
+DA:89,0
+DA:90,0
+DA:91,0
+DA:93,0
+DA:96,0
+DA:97,0
+DA:98,0
+DA:99,0
+DA:101,0
+DA:102,0
+DA:106,0
+DA:108,0
+DA:213,0
+DA:214,0
+DA:215,0
+DA:217,0
+DA:218,0
+DA:219,0
+DA:220,0
+DA:222,0
+DA:223,0
+DA:224,0
+DA:226,0
+DA:227,0
+DA:228,0
+DA:229,0
+DA:231,0
+DA:232,0
+LF:77
+LH:3
+FN:21,36,JupyterBackend.__init__
+FNDA:0,JupyterBackend.__init__
+FN:38,39,JupyterBackend.get_device_count
+FNDA:0,JupyterBackend.get_device_count
+FN:41,42,JupyterBackend.get_device_info_by_index
+FNDA:0,JupyterBackend.get_device_info_by_index
+FN:44,45,JupyterBackend.get_default_input_device_info
+FNDA:0,JupyterBackend.get_default_input_device_info
+FN:47,48,JupyterBackend.get_default_output_device_info
+FNDA:0,JupyterBackend.get_default_output_device_info
+FN:50,66,JupyterBackend.open
+FNDA:0,JupyterBackend.open
+FN:68,69,JupyterBackend.process_buffer
+FNDA:0,JupyterBackend.process_buffer
+FN:71,72,JupyterBackend.terminate
+FNDA:0,JupyterBackend.terminate
+FN:76,211,JupyterStream.__init__
+FNDA:0,JupyterStream.__init__
+FN:83,87,JupyterStream.__init__.bridge
+FNDA:0,JupyterStream.__init__.bridge
+FN:89,91,JupyterStream.__init__.ws_runner
+FNDA:0,JupyterStream.__init__.ws_runner
+FN:93,99,JupyterStream.__init__.loop_thread
+FNDA:0,JupyterStream.__init__.loop_thread
+FN:214,215,JupyterStream.set_buffer_threshold
+FNDA:0,JupyterStream.set_buffer_threshold
+FN:217,220,JupyterStream.stop_stream
+FNDA:0,JupyterStream.stop_stream
+FN:222,224,JupyterStream.close
+FNDA:0,JupyterStream.close
+FN:226,229,JupyterStream.start_stream
+FNDA:0,JupyterStream.start_stream
+FN:231,232,JupyterStream.is_active
+FNDA:0,JupyterStream.is_active
+FNF:17
+FNH:0
+end_of_record
+SF:pya/backend/PyAudio.py
+DA:1,1
+DA:3,1
+DA:5,0
+DA:7,0
+DA:12,0
+DA:13,0
+DA:14,0
+DA:16,0
+DA:17,0
+DA:18,0
+DA:19,0
+DA:20,0
+DA:21,0
+DA:22,0
+DA:23,0
+DA:24,0
+DA:26,0
+DA:30,0
+DA:31,0
+DA:33,0
+DA:34,0
+DA:36,0
+DA:37,0
+DA:39,0
+DA:40,0
+DA:42,0
+DA:56,0
+DA:70,0
+DA:71,0
+DA:73,0
+DA:74,0
+DA:76,0
+DA:77,0
+DA:78,0
+DA:79,0
+LF:35
+LH:2
+FN:16,28,PyAudioBackend.__init__
+FNDA:0,PyAudioBackend.__init__
+FN:30,31,PyAudioBackend.get_device_count
+FNDA:0,PyAudioBackend.get_device_count
+FN:33,34,PyAudioBackend.get_device_info_by_index
+FNDA:0,PyAudioBackend.get_device_info_by_index
+FN:36,37,PyAudioBackend.get_default_input_device_info
+FNDA:0,PyAudioBackend.get_default_input_device_info
+FN:39,40,PyAudioBackend.get_default_output_device_info
+FNDA:0,PyAudioBackend.get_default_output_device_info
+FN:42,71,PyAudioBackend.open
+FNDA:0,PyAudioBackend.open
+FN:73,74,PyAudioBackend.process_buffer
+FNDA:0,PyAudioBackend.process_buffer
+FN:76,79,PyAudioBackend.terminate
+FNDA:0,PyAudioBackend.terminate
+FNF:8
+FNH:0
+end_of_record
+SF:pya/backend/__init__.py
+DA:1,1
+DA:3,1
+DA:4,1
+DA:6,1
+DA:7,1
+DA:9,1
+DA:11,1
+DA:12,1
+DA:14,0
+DA:19,1
+DA:20,1
+DA:22,0
+LF:12
+LH:10
+end_of_record
+SF:pya/backend/base.py
+DA:1,1
+DA:4,1
+DA:5,1
+DA:6,1
+DA:9,1
+DA:10,1
+DA:13,1
+DA:14,1
+DA:17,1
+DA:18,1
+DA:21,1
+DA:22,1
+DA:25,1
+DA:26,1
+DA:29,1
+DA:30,1
+DA:34,1
+DA:35,1
+DA:36,1
+DA:39,1
+DA:40,1
+DA:43,1
+DA:44,1
+DA:47,1
+DA:48,1
+LF:25
+LH:25
+FN:6,7,BackendBase.get_device_count
+FNDA:0,BackendBase.get_device_count
+FN:10,11,BackendBase.get_device_info_by_index
+FNDA:0,BackendBase.get_device_info_by_index
+FN:14,15,BackendBase.get_default_output_device_info
+FNDA:0,BackendBase.get_default_output_device_info
+FN:18,19,BackendBase.get_default_input_device_info
+FNDA:0,BackendBase.get_default_input_device_info
+FN:22,23,BackendBase.open
+FNDA:0,BackendBase.open
+FN:26,27,BackendBase.terminate
+FNDA:0,BackendBase.terminate
+FN:30,31,BackendBase.process_buffer
+FNDA:0,BackendBase.process_buffer
+FN:36,37,StreamBase.is_active
+FNDA:0,StreamBase.is_active
+FN:40,41,StreamBase.start_stream
+FNDA:0,StreamBase.start_stream
+FN:44,45,StreamBase.stop_stream
+FNDA:0,StreamBase.stop_stream
+FN:48,49,StreamBase.close
+FNDA:0,StreamBase.close
+FNF:11
+FNH:0
+end_of_record
+SF:pya/helper/__init__.py
+DA:4,1
+DA:5,1
+DA:6,1
+LF:3
+LH:3
+end_of_record
+SF:pya/helper/backend.py
+DA:1,1
+DA:3,1
+DA:4,0
+DA:5,0
+DA:6,0
+DA:9,1
+DA:17,1
+DA:18,0
+DA:19,0
+DA:21,0
+DA:22,0
+DA:23,0
+DA:25,0
+DA:28,0
+DA:29,0
+DA:30,0
+DA:34,0
+DA:35,0
+DA:36,0
+DA:37,0
+DA:40,1
+DA:41,0
+DA:42,0
+DA:44,0
+DA:45,0
+DA:46,0
+DA:49,1
+DA:50,0
+DA:52,0
+DA:54,0
+DA:55,0
+DA:61,0
+DA:62,0
+DA:63,0
+DA:65,0
+DA:68,1
+DA:90,0
+DA:91,0
+DA:92,0
+DA:93,0
+DA:94,0
+DA:98,0
+LF:42
+LH:7
+FN:17,37,get_server_info
+FNDA:0,get_server_info
+FN:40,46,try_pyaudio_backend
+FNDA:0,try_pyaudio_backend
+FN:49,65,try_jupyter_backend
+FNDA:0,try_jupyter_backend
+FN:68,98,determine_backend
+FNDA:0,determine_backend
+FNF:4
+FNH:0
+end_of_record
+SF:pya/helper/codec.py
+DA:8,1
+DA:9,1
+DA:10,1
+DA:11,1
+DA:12,1
+DA:13,1
+DA:14,1
+DA:16,1
+DA:17,1
+DA:19,1
+DA:38,1
+DA:40,1
+DA:41,0
+DA:43,1
+DA:46,1
+DA:50,1
+DA:54,1
+DA:60,1
+DA:64,1
+DA:68,1
+DA:72,1
+DA:76,1
+DA:80,1
+DA:84,1
+DA:87,1
+DA:88,1
+DA:89,1
+DA:90,1
+DA:91,1
+DA:92,1
+DA:94,1
+DA:95,1
+DA:97,1
+DA:99,1
+DA:100,1
+DA:102,1
+DA:104,1
+DA:105,1
+DA:107,0
+DA:109,1
+DA:124,1
+DA:128,1
+DA:129,1
+DA:131,1
+DA:132,1
+DA:133,1
+DA:135,1
+DA:136,0
+DA:139,1
+DA:142,1
+DA:143,1
+DA:144,1
+DA:145,1
+DA:146,1
+DA:147,1
+DA:148,1
+DA:149,1
+DA:150,1
+DA:151,1
+DA:153,1
+DA:154,1
+DA:156,1
+DA:158,1
+DA:165,1
+DA:167,1
+DA:169,1
+DA:170,0
+DA:171,0
+DA:173,1
+DA:175,1
+DA:176,1
+DA:177,1
+DA:178,1
+DA:180,1
+DA:181,1
+DA:182,1
+DA:184,1
+DA:186,1
+DA:187,1
+DA:190,1
+DA:194,1
+DA:195,1
+DA:196,1
+DA:197,1
+DA:198,1
+DA:199,1
+DA:200,1
+DA:202,1
+DA:203,1
+DA:204,1
+DA:205,1
+DA:206,1
+DA:207,1
+DA:208,1
+DA:211,1
+DA:219,1
+DA:220,1
+DA:221,1
+DA:222,1
+DA:223,0
+DA:224,0
+DA:226,0
+DA:229,1
+DA:231,1
+DA:232,1
+DA:239,0
+DA:240,0
+DA:242,1
+DA:243,1
+DA:248,1
+DA:251,1
+DA:254,1
+DA:255,1
+DA:260,1
+DA:262,1
+DA:263,0
+DA:264,0
+DA:265,0
+DA:269,0
+DA:272,0
+DA:275,1
+DA:276,1
+DA:278,1
+DA:287,0
+DA:288,0
+DA:294,1
+DA:295,0
+DA:296,0
+DA:298,0
+DA:300,0
+DA:304,1
+DA:305,1
+DA:308,1
+DA:309,1
+DA:314,1
+DA:315,1
+DA:317,1
+DA:318,1
+DA:320,0
+DA:322,1
+DA:324,1
+DA:325,1
+DA:326,1
+DA:327,1
+DA:329,0
+DA:331,1
+DA:332,1
+DA:334,1
+DA:336,1
+DA:337,0
+DA:338,1
+DA:339,0
+DA:340,1
+DA:341,1
+DA:342,1
+DA:343,1
+DA:344,1
+DA:345,1
+DA:346,1
+DA:348,1
+DA:354,1
+DA:355,1
+DA:356,1
+DA:358,0
+DA:361,1
+DA:362,1
+DA:363,1
+DA:364,1
+DA:365,0
+DA:367,1
+DA:368,1
+DA:369,0
+DA:371,1
+DA:373,0
+DA:376,1
+DA:377,1
+DA:378,1
+DA:379,1
+DA:386,0
+DA:388,1
+DA:390,1
+DA:392,1
+DA:393,1
+DA:394,1
+DA:395,1
+DA:396,0
+DA:399,1
+DA:401,1
+DA:402,0
+DA:404,1
+DA:406,1
+DA:407,0
+DA:408,0
+DA:409,0
+DA:414,0
+DA:416,1
+DA:418,1
+DA:423,1
+DA:426,1
+DA:427,1
+DA:428,1
+DA:432,1
+DA:433,1
+DA:434,1
+DA:435,1
+DA:440,1
+DA:441,1
+DA:444,1
+DA:445,1
+DA:448,1
+DA:467,1
+DA:468,1
+DA:470,1
+DA:471,1
+DA:474,1
+DA:475,1
+DA:477,1
+LF:217
+LH:181
+FN:87,92,BaseAudioFile.__init__
+FNDA:1,BaseAudioFile.__init__
+FN:95,97,BaseAudioFile.channels
+FNDA:1,BaseAudioFile.channels
+FN:100,102,BaseAudioFile.samplerate
+FNDA:1,BaseAudioFile.samplerate
+FN:105,107,BaseAudioFile.duration
+FNDA:0,BaseAudioFile.duration
+FN:109,122,BaseAudioFile.read_data
+FNDA:0,BaseAudioFile.read_data
+FN:124,126,BaseAudioFile.close
+FNDA:0,BaseAudioFile.close
+FN:128,129,BaseAudioFile.__enter__
+FNDA:1,BaseAudioFile.__enter__
+FN:131,133,BaseAudioFile.__exit__
+FNDA:1,BaseAudioFile.__exit__
+FN:135,136,BaseAudioFile.__iter__
+FNDA:0,BaseAudioFile.__iter__
+FN:142,154,SoundFileAudioFile.__init__
+FNDA:1,SoundFileAudioFile.__init__
+FN:156,165,SoundFileAudioFile._get_bytes_per_sample
+FNDA:1,SoundFileAudioFile._get_bytes_per_sample
+FN:167,171,SoundFileAudioFile._check
+FNDA:1,SoundFileAudioFile._check
+FN:173,182,SoundFileAudioFile.read_data
+FNDA:1,SoundFileAudioFile.read_data
+FN:184,187,SoundFileAudioFile.close
+FNDA:1,SoundFileAudioFile.close
+FN:194,200,QueueReaderThread.__init__
+FNDA:1,QueueReaderThread.__init__
+FN:202,208,QueueReaderThread.run
+FNDA:1,QueueReaderThread.run
+FN:211,226,popen_multiple
+FNDA:1,popen_multiple
+FN:229,243,ffmpeg_available
+FNDA:1,ffmpeg_available
+FN:254,315,FFmpegAudioFile.__init__
+FNDA:1,FFmpegAudioFile.__init__
+FN:318,320,FFmpegAudioFile.raw_str_info
+FNDA:0,FFmpegAudioFile.raw_str_info
+FN:322,346,FFmpegAudioFile._get_info
+FNDA:1,FFmpegAudioFile._get_info
+FN:348,386,FFmpegAudioFile._parse_info
+FNDA:1,FFmpegAudioFile._parse_info
+FN:388,414,FFmpegAudioFile.read_data
+FNDA:1,FFmpegAudioFile.read_data
+FN:416,445,FFmpegAudioFile.close
+FNDA:1,FFmpegAudioFile.close
+FN:448,477,audio_read
+FNDA:1,audio_read
+FNF:25
+FNH:20
+end_of_record
+SF:pya/helper/helpers.py
+DA:2,1
+DA:3,1
+DA:4,1
+DA:6,1
+DA:7,1
+DA:9,1
+DA:11,1
+DA:30,1
+DA:53,1
+DA:54,1
+DA:55,1
+DA:56,1
+DA:58,1
+DA:59,1
+DA:60,1
+DA:61,1
+DA:64,1
+DA:67,1
+DA:68,1
+DA:69,1
+DA:72,1
+DA:76,0
+DA:77,0
+DA:78,0
+DA:79,0
+DA:80,0
+DA:82,0
+DA:83,0
+DA:85,0
+DA:86,0
+DA:88,0
+DA:91,1
+DA:112,0
+DA:114,0
+DA:116,0
+DA:119,1
+DA:120,0
+DA:121,0
+DA:122,0
+DA:123,0
+DA:124,0
+DA:126,0
+DA:129,1
+DA:131,0
+DA:132,0
+DA:133,0
+DA:134,0
+DA:135,0
+DA:136,0
+DA:137,0
+DA:138,0
+DA:139,0
+DA:140,0
+DA:141,0
+DA:142,0
+DA:143,0
+DA:146,1
+DA:147,0
+DA:148,0
+DA:149,0
+DA:150,0
+DA:151,0
+DA:155,0
+DA:156,0
+DA:159,1
+DA:181,1
+DA:182,1
+DA:183,1
+DA:184,1
+DA:185,1
+DA:188,1
+DA:189,1
+DA:193,0
+DA:198,1
+DA:200,1
+DA:203,1
+DA:217,1
+DA:218,1
+DA:219,1
+DA:222,1
+DA:224,1
+DA:231,1
+DA:232,1
+DA:233,1
+DA:234,1
+DA:237,1
+DA:259,1
+DA:260,1
+DA:261,1
+DA:262,1
+DA:263,0
+DA:265,1
+DA:266,1
+DA:267,1
+DA:269,1
+DA:270,1
+DA:271,1
+DA:273,1
+DA:274,1
+DA:276,0
+DA:282,0
+DA:283,0
+DA:284,0
+DA:285,0
+DA:287,0
+DA:288,0
+DA:289,1
+DA:292,1
+DA:309,1
+DA:310,1
+DA:314,1
+DA:315,1
+DA:318,1
+DA:335,1
+LF:114
+LH:66
+FN:30,61,spectrum
+FNDA:1,spectrum
+FN:64,69,normalize
+FNDA:1,normalize
+FN:72,88,audio_from_file
+FNDA:0,audio_from_file
+FN:91,116,buf_to_float
+FNDA:0,buf_to_float
+FN:119,126,_try_initializing_pyaudio
+FNDA:0,_try_initializing_pyaudio
+FN:129,143,device_info
+FNDA:0,device_info
+FN:146,156,find_device
+FNDA:0,find_device
+FN:159,195,padding
+FNDA:1,padding
+FN:198,200,is_pow2
+FNDA:1,is_pow2
+FN:203,219,next_pow2
+FNDA:1,next_pow2
+FN:222,228,round_half_up
+FNDA:1,round_half_up
+FN:231,234,rolling_window
+FNDA:1,rolling_window
+FN:237,289,signal_to_frame
+FNDA:1,signal_to_frame
+FN:292,315,magspec
+FNDA:1,magspec
+FN:318,335,powspec
+FNDA:1,powspec
+FNF:15
+FNH:10
+end_of_record
+SF:pya/helper/visualization.py
+DA:1,1
+DA:3,1
+DA:5,1
+DA:6,1
+DA:7,1
+DA:8,1
+DA:10,1
+DA:13,1
+DA:47,1
+DA:48,1
+DA:53,1
+DA:54,1
+DA:56,1
+DA:58,1
+DA:61,1
+DA:62,1
+DA:64,1
+DA:65,1
+DA:66,1
+DA:67,1
+DA:68,1
+DA:69,1
+DA:70,0
+DA:71,0
+DA:72,0
+DA:79,0
+DA:80,0
+DA:81,0
+DA:82,1
+DA:83,1
+DA:84,1
+DA:85,1
+DA:86,1
+DA:88,1
+DA:89,1
+DA:90,1
+DA:91,1
+DA:92,1
+DA:95,1
+DA:129,1
+DA:131,1
+DA:133,1
+DA:134,1
+DA:135,1
+DA:136,1
+DA:138,1
+DA:140,1
+DA:141,1
+DA:143,1
+DA:144,1
+DA:145,1
+DA:146,1
+DA:147,1
+DA:149,1
+DA:150,1
+DA:152,1
+DA:153,1
+DA:154,1
+DA:155,1
+DA:156,1
+DA:157,1
+DA:159,1
+DA:165,1
+DA:166,1
+DA:167,1
+DA:168,1
+DA:169,1
+DA:170,1
+DA:171,1
+DA:172,1
+DA:173,1
+DA:174,1
+DA:175,1
+DA:176,1
+DA:177,1
+DA:178,1
+DA:179,1
+LF:77
+LH:71
+FN:13,92,basicplot
+FNDA:1,basicplot
+FN:95,179,gridplot
+FNDA:1,gridplot
+FNF:2
+FNH:2
+end_of_record
+SF:pya/ugen.py
+DA:1,1
+DA:3,1
+DA:4,1
+DA:6,1
+DA:7,1
+DA:10,1
+DA:18,1
+DA:19,1
+DA:20,1
+DA:21,1
+DA:22,1
+DA:23,1
+DA:25,1
+DA:30,1
+DA:49,1
+DA:50,1
+DA:52,1
+DA:91,1
+DA:92,1
+DA:95,1
+DA:96,1
+DA:97,1
+DA:98,1
+DA:100,1
+DA:139,1
+DA:140,1
+DA:143,1
+DA:144,1
+DA:145,1
+DA:146,1
+DA:148,1
+DA:191,1
+DA:192,1
+DA:202,1
+DA:203,1
+DA:204,1
+DA:205,1
+DA:207,1
+DA:249,1
+DA:250,1
+DA:254,1
+DA:255,1
+DA:256,1
+DA:257,1
+DA:259,1
+DA:299,1
+DA:301,1
+DA:302,1
+DA:304,1
+DA:306,1
+DA:307,1
+DA:308,1
+DA:309,1
+DA:310,1
+DA:311,1
+DA:312,1
+DA:313,1
+DA:314,1
+DA:315,1
+DA:316,1
+DA:317,1
+DA:318,1
+DA:319,1
+DA:320,1
+DA:321,1
+DA:322,1
+LF:66
+LH:66
+FN:10,27,get_num_of_rows
+FNDA:1,get_num_of_rows
+FN:49,50,Ugen.__init__
+FNDA:1,Ugen.__init__
+FN:52,98,Ugen.sine
+FNDA:1,Ugen.sine
+FN:100,146,Ugen.cos
+FNDA:1,Ugen.cos
+FN:148,205,Ugen.square
+FNDA:1,Ugen.square
+FN:207,257,Ugen.sawtooth
+FNDA:1,Ugen.sawtooth
+FN:259,322,Ugen.noise
+FNDA:1,Ugen.noise
+FNF:7
+FNH:7
+end_of_record
+SF:pya/version.py
+DA:1,1
+LF:1
+LH:1
+end_of_record
diff --git a/dev/generate_doc b/dev/generate_doc
index 6ae18af4..07680d5c 100755
--- a/dev/generate_doc
+++ b/dev/generate_doc
@@ -1,12 +1,12 @@
#!/usr/bin/env python
import argparse
-import sys
-import os
-import subprocess
+import os
import shutil
+import subprocess
+import sys
+from os.path import basename, dirname, exists
from sys import platform
-from os.path import exists, dirname, basename
SILENCE = "> /dev/null 2>&1"
@@ -14,19 +14,41 @@ SILENCE = "> /dev/null 2>&1"
# you usually want to run:
# python dev/generate_doc --doctree --publish --clean --no-show
+
def generate():
- git_root = subprocess.check_output(f'git -C {dirname(__file__)} rev-parse --show-toplevel'.split(' '))
- git_root = str(git_root, 'utf-8').strip()
+ git_root = subprocess.check_output(
+ f"git -C {dirname(__file__)} rev-parse --show-toplevel".split(" ")
+ )
+ git_root = str(git_root, "utf-8").strip()
parser = argparse.ArgumentParser(description="Generates Sphinx documentation")
- parser.add_argument('--doctree', action='store_true', help='build complete doctree')
- parser.add_argument('--publish', action='store_true', help='build and publish doctree')
- parser.add_argument('--no-show', action='store_true', help='do not open browser after build')
- parser.add_argument('--branches', nargs='*', default=['master', 'develop'], help='limit doctree to these branches')
- parser.add_argument('--tags', nargs='*', default=False, help='limit doctree to these tags')
- parser.add_argument('--input', default=f"{git_root}/docs", help='input folder (ignored for doctree)')
- parser.add_argument('--out', default=f"{git_root}/build", help='output folder')
- parser.add_argument('--template-folder', default=f"{git_root}/docs/_templates", help="templates used for doctree")
- parser.add_argument('--clean', action='store_true', help="removes out folder before building doc")
+ parser.add_argument("--doctree", action="store_true", help="build complete doctree")
+ parser.add_argument(
+ "--publish", action="store_true", help="build and publish doctree"
+ )
+ parser.add_argument(
+ "--no-show", action="store_true", help="do not open browser after build"
+ )
+ parser.add_argument(
+ "--branches",
+ nargs="*",
+ default=["master", "develop"],
+ help="limit doctree to these branches",
+ )
+ parser.add_argument(
+ "--tags", nargs="*", default=False, help="limit doctree to these tags"
+ )
+ parser.add_argument(
+ "--input", default=f"{git_root}/docs", help="input folder (ignored for doctree)"
+ )
+ parser.add_argument("--out", default=f"{git_root}/build", help="output folder")
+ parser.add_argument(
+ "--template-folder",
+ default=f"{git_root}/docs/_templates",
+ help="templates used for doctree",
+ )
+ parser.add_argument(
+ "--clean", action="store_true", help="removes out folder before building doc"
+ )
args = parser.parse_args()
args.doctree = args.doctree if not args.publish else True
if args.clean and exists(args.out):
@@ -35,39 +57,60 @@ def generate():
if not args.doctree:
generate_local(doc=args.input, out=args.out, show=not args.no_show)
else:
- generate_tree(out_folder=args.out, publish=args.publish, branches=args.branches,
- tags=args.tags, template_folder=args.template_folder, show=not args.no_show)
-
-
-def generate_local(doc, out, show, target='html'):
- os.system(f'sphinx-build -b {target} {doc} {out}/{target}')
+ generate_tree(
+ out_folder=args.out,
+ publish=args.publish,
+ branches=args.branches,
+ tags=args.tags,
+ template_folder=args.template_folder,
+ show=not args.no_show,
+ )
+
+
+def generate_local(doc, out, show, target="html"):
+ os.system(f"sphinx-build -b {target} {doc} {out}/{target}")
if show:
- url = f'{out}/{target}/index.{target}'
- if platform == 'darwin':
- os.system(f'open {url}')
- elif platform == 'win32':
+ url = f"{out}/{target}/index.{target}"
+ if platform == "darwin":
+ os.system(f"open {url}")
+ elif platform == "win32":
os.startfile(url)
else:
raise NotImplementedError("'show' is not available for your platform")
-def generate_tree(out_folder, publish=False, branches=['master', 'develop'], tags=None, template_folder=None, show=False):
+def generate_tree(
+ out_folder,
+ publish=False,
+ branches=["master", "develop"],
+ tags=None,
+ template_folder=None,
+ show=False,
+):
doctree_root = f"{out_folder}/doctree/pya"
build_folder = f"{out_folder}/tmp"
os.makedirs(build_folder, exist_ok=True)
if not exists(doctree_root):
- os.system(f'git clone https://github.com/interactive-sonification/pya.git {doctree_root}')
+ os.system(
+ f"git clone https://github.com/interactive-sonification/pya.git {doctree_root}"
+ )
else:
# os.system(f'git -C {doctree_root} fetch --all')
- os.system(f'git -C {doctree_root} pull --all')
+ os.system(f"git -C {doctree_root} pull --all")
if tags is False:
- out = subprocess.check_output(f"git -C {doctree_root} show-ref --tags -d".split(' '))
- tags = [str(line.split(b' ')[1].split(b'/')[2], 'utf-8') for line in out.split(b'\n')[::-1] if len(line)]
+ out = subprocess.check_output(
+ f"git -C {doctree_root} show-ref --tags -d".split(" ")
+ )
+ tags = [
+ str(line.split(b" ")[1].split(b"/")[2], "utf-8")
+ for line in out.split(b"\n")[::-1]
+ if len(line)
+ ]
# first, check which documentation to generate
branches = [b for b in branches if _has_docs(b, doctree_root)]
- tags = [t for t in tags if _has_docs('tags/' + t, doctree_root)]
+ tags = [t for t in tags if _has_docs("tags/" + t, doctree_root)]
print(f"Will generate documentation for:\nBranches: {branches}\nTags: {tags}")
# fix order of dropdown elements (most recent tag first, then branches and older tags)
@@ -76,28 +119,37 @@ def generate_tree(out_folder, publish=False, branches=['master', 'develop'], tag
# generate documentation; all versions have to be known for the dropdown menu
for d in doclist:
print(f"Generating documentation for {d} ...")
- target = d if d in branches else 'tags/' + d
- res = os.system(f'git -C {doctree_root} checkout {target} -f' + SILENCE)
+ target = d if d in branches else "tags/" + d
+ res = os.system(f"git -C {doctree_root} checkout {target} -f" + SILENCE)
if res != 0:
- raise RuntimeError(f'Could not checkout {d}. Git returned status code {res}!')
- os.system(f'cp {template_folder}/../conf.py {doctree_root}/docs/')
+ raise RuntimeError(
+ f"Could not checkout {d}. Git returned status code {res}!"
+ )
+ os.system(f"cp {template_folder}/../conf.py {doctree_root}/docs/")
if template_folder:
- os.system(f'cp {template_folder}/* {doctree_root}/docs/_templates')
+ os.system(f"cp {template_folder}/* {doctree_root}/docs/_templates")
# override index and config for versions older than 0.5.0
- if d[0] == 'v' and d[1] == '0' and int(d[3]) < 5:
- os.system(f'cp {template_folder}/../conf.py {template_folder}/../index.rst {doctree_root}/docs')
+ if d[0] == "v" and d[1] == "0" and int(d[3]) < 5:
+ os.system(
+ f"cp {template_folder}/../conf.py {template_folder}/../index.rst {doctree_root}/docs"
+ )
# PYTHONDONTWRITEBYTECODE=1 prevents __pycache__ files which we don't need when code runs only once.
- call = f'PYTHONDONTWRITEBYTECODE=1 sphinx-build -b html -D version={d} -A versions={",".join(doclist)} {doctree_root}/docs {build_folder}/{d}' + SILENCE
+ call = (
+ f"PYTHONDONTWRITEBYTECODE=1 sphinx-build -b html -D version={d} -A versions={','.join(doclist)} {doctree_root}/docs {build_folder}/{d}"
+ + SILENCE
+ )
print(call)
res = os.system(call)
if res != 0:
- raise RuntimeError(f'Could not generate documentation for {d}. Sphinx returned status code {res}!')
+ raise RuntimeError(
+ f"Could not generate documentation for {d}. Sphinx returned status code {res}!"
+ )
# create index html to forward to last tagged version
if doclist:
- with open(f'{build_folder}/index.html', 'w') as fp:
+ with open(f"{build_folder}/index.html", "w") as fp:
fp.write(f"""
@@ -108,48 +160,53 @@ def generate_tree(out_folder, publish=False, branches=['master', 'develop'], tag
# prepare gh-pages
print("Merging documentation...")
- os.system(f'git -C {doctree_root} checkout gh-pages -f' + SILENCE)
- os.system(f'cp -r {build_folder}/* {doctree_root}')
+ os.system(f"git -C {doctree_root} checkout gh-pages -f" + SILENCE)
+ os.system(f"cp -r {build_folder}/* {doctree_root}")
print("Current differences in 'gh-branch':")
- os.system(f'git -C {doctree_root} status')
+ os.system(f"git -C {doctree_root} status")
print(f"Documentation tree has been written to {doctree_root}")
# commit and push changes when publish has been passed
if publish:
- os.system(f'git -C {doctree_root} add -A')
+ os.system(f"git -C {doctree_root} add -A")
os.system(f'git -C {doctree_root} commit -a -m "update doctree"')
- os.system(f'git -C {doctree_root} push')
+ os.system(f"git -C {doctree_root} push")
if show:
_run_webserver(doctree_root)
+
def _has_docs(name, doctree_root):
- os.system(f'git -C {doctree_root} checkout {name}' + SILENCE)
- return exists(f'{doctree_root}/docs')
+ os.system(f"git -C {doctree_root} checkout {name}" + SILENCE)
+ return exists(f"{doctree_root}/docs")
+
def _run_webserver(root):
- import threading
- import time
import http.server
import socketserver
+ import threading
+ import time
def _delayed_open():
- url = f'http://localhost:8181/{basename(root)}/index.html'
+ url = f"http://localhost:8181/{basename(root)}/index.html"
time.sleep(0.2)
- if sys.platform == 'darwin':
- os.system(f'open {url}')
- elif sys.platform == 'win32':
+ if sys.platform == "darwin":
+ os.system(f"open {url}")
+ elif sys.platform == "win32":
os.startfile(url)
else:
raise NotImplementedError("'show' is not available for your platform")
t = threading.Thread(target=_delayed_open)
t.start()
+
class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
- super().__init__(*args, directory=root + '/../', **kwargs)
+ super().__init__(*args, directory=root + "/../", **kwargs)
+
def log_message(self, format, *args):
pass
+
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", 8181), Handler) as httpd:
try:
diff --git a/docs/_autosummary/pya.amfcc.rst b/docs/_autosummary/pya.amfcc.rst
new file mode 100644
index 00000000..8183fafb
--- /dev/null
+++ b/docs/_autosummary/pya.amfcc.rst
@@ -0,0 +1,26 @@
+pya.amfcc
+=========
+
+.. automodule:: pya.amfcc
+
+
+
+
+
+
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ Amfcc
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.arecorder.rst b/docs/_autosummary/pya.arecorder.rst
new file mode 100644
index 00000000..263fc55f
--- /dev/null
+++ b/docs/_autosummary/pya.arecorder.rst
@@ -0,0 +1,26 @@
+pya.arecorder
+=============
+
+.. automodule:: pya.arecorder
+
+
+
+
+
+
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ Arecorder
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.aserver.rst b/docs/_autosummary/pya.aserver.rst
new file mode 100644
index 00000000..9509f076
--- /dev/null
+++ b/docs/_autosummary/pya.aserver.rst
@@ -0,0 +1,26 @@
+pya.aserver
+===========
+
+.. automodule:: pya.aserver
+
+
+
+
+
+
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ Aserver
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.asig.rst b/docs/_autosummary/pya.asig.rst
new file mode 100644
index 00000000..fa46fd36
--- /dev/null
+++ b/docs/_autosummary/pya.asig.rst
@@ -0,0 +1,26 @@
+pya.asig
+========
+
+.. automodule:: pya.asig
+
+
+
+
+
+
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ Asig
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.aspec.rst b/docs/_autosummary/pya.aspec.rst
new file mode 100644
index 00000000..a1c9e217
--- /dev/null
+++ b/docs/_autosummary/pya.aspec.rst
@@ -0,0 +1,26 @@
+pya.aspec
+=========
+
+.. automodule:: pya.aspec
+
+
+
+
+
+
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ Aspec
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.astft.rst b/docs/_autosummary/pya.astft.rst
new file mode 100644
index 00000000..5aacb4f9
--- /dev/null
+++ b/docs/_autosummary/pya.astft.rst
@@ -0,0 +1,26 @@
+pya.astft
+=========
+
+.. automodule:: pya.astft
+
+
+
+
+
+
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ Astft
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.backend.Dummy.rst b/docs/_autosummary/pya.backend.Dummy.rst
new file mode 100644
index 00000000..08963929
--- /dev/null
+++ b/docs/_autosummary/pya.backend.Dummy.rst
@@ -0,0 +1,27 @@
+pya.backend.Dummy
+=================
+
+.. automodule:: pya.backend.Dummy
+
+
+
+
+
+
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ DummyBackend
+ DummyStream
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.backend.base.rst b/docs/_autosummary/pya.backend.base.rst
new file mode 100644
index 00000000..899d98af
--- /dev/null
+++ b/docs/_autosummary/pya.backend.base.rst
@@ -0,0 +1,27 @@
+pya.backend.base
+================
+
+.. automodule:: pya.backend.base
+
+
+
+
+
+
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ BackendBase
+ StreamBase
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.backend.rst b/docs/_autosummary/pya.backend.rst
new file mode 100644
index 00000000..00e396c3
--- /dev/null
+++ b/docs/_autosummary/pya.backend.rst
@@ -0,0 +1,29 @@
+pya.backend
+===========
+
+.. automodule:: pya.backend
+
+
+
+
+
+
+
+ .. rubric:: Functions
+
+ .. autosummary::
+
+ determine_backend
+ get_server_info
+ try_jupyter_backend
+ try_pyaudio_backend
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.helper.backend.rst b/docs/_autosummary/pya.helper.backend.rst
new file mode 100644
index 00000000..f9ac5e11
--- /dev/null
+++ b/docs/_autosummary/pya.helper.backend.rst
@@ -0,0 +1,29 @@
+pya.helper.backend
+==================
+
+.. automodule:: pya.helper.backend
+
+
+
+
+
+
+
+ .. rubric:: Functions
+
+ .. autosummary::
+
+ determine_backend
+ get_server_info
+ try_jupyter_backend
+ try_pyaudio_backend
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.helper.codec.rst b/docs/_autosummary/pya.helper.codec.rst
new file mode 100644
index 00000000..1f9cb354
--- /dev/null
+++ b/docs/_autosummary/pya.helper.codec.rst
@@ -0,0 +1,51 @@
+pya.helper.codec
+================
+
+.. automodule:: pya.helper.codec
+
+
+
+
+
+
+
+ .. rubric:: Functions
+
+ .. autosummary::
+
+ audio_read
+ ffmpeg_available
+ popen_multiple
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ BaseAudioFile
+ FFmpegAudioFile
+ QueueReaderThread
+ SoundFileAudioFile
+
+
+
+
+
+ .. rubric:: Exceptions
+
+ .. autosummary::
+
+ BitWidthError
+ CommunicationError
+ DecodeError
+ FFmpegError
+ FFmpegNotInstalledError
+ FFmpegReadTimeoutError
+ NoBackendError
+ NoFileError
+ UnsupportedError
+
+
diff --git a/docs/_autosummary/pya.helper.helpers.rst b/docs/_autosummary/pya.helper.helpers.rst
new file mode 100644
index 00000000..85eb4ea3
--- /dev/null
+++ b/docs/_autosummary/pya.helper.helpers.rst
@@ -0,0 +1,39 @@
+pya.helper.helpers
+==================
+
+.. automodule:: pya.helper.helpers
+
+
+
+
+
+
+
+ .. rubric:: Functions
+
+ .. autosummary::
+
+ audio_from_file
+ buf_to_float
+ device_info
+ find_device
+ is_pow2
+ magspec
+ next_pow2
+ normalize
+ padding
+ powspec
+ rolling_window
+ round_half_up
+ signal_to_frame
+ spectrum
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.helper.rst b/docs/_autosummary/pya.helper.rst
new file mode 100644
index 00000000..32e92b39
--- /dev/null
+++ b/docs/_autosummary/pya.helper.rst
@@ -0,0 +1,33 @@
+pya.helper
+==========
+
+.. automodule:: pya.helper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.. rubric:: Modules
+
+.. autosummary::
+ :toctree:
+ :recursive:
+
+ pya.helper.backend
+ pya.helper.codec
+ pya.helper.helpers
+ pya.helper.visualization
diff --git a/docs/_autosummary/pya.helper.visualization.rst b/docs/_autosummary/pya.helper.visualization.rst
new file mode 100644
index 00000000..73bc171e
--- /dev/null
+++ b/docs/_autosummary/pya.helper.visualization.rst
@@ -0,0 +1,27 @@
+pya.helper.visualization
+========================
+
+.. automodule:: pya.helper.visualization
+
+
+
+
+
+
+
+ .. rubric:: Functions
+
+ .. autosummary::
+
+ basicplot
+ gridplot
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.rst b/docs/_autosummary/pya.rst
new file mode 100644
index 00000000..aa599b55
--- /dev/null
+++ b/docs/_autosummary/pya.rst
@@ -0,0 +1,46 @@
+pya
+===
+
+.. automodule:: pya
+
+
+
+
+
+
+
+ .. rubric:: Functions
+
+ .. autosummary::
+
+ shutdown
+ startup
+
+
+
+
+
+
+
+
+
+
+
+
+
+.. rubric:: Modules
+
+.. autosummary::
+ :toctree:
+ :recursive:
+
+ pya.amfcc
+ pya.arecorder
+ pya.aserver
+ pya.asig
+ pya.aspec
+ pya.astft
+ pya.backend
+ pya.helper
+ pya.ugen
+ pya.version
diff --git a/docs/_autosummary/pya.ugen.rst b/docs/_autosummary/pya.ugen.rst
new file mode 100644
index 00000000..ecf8966a
--- /dev/null
+++ b/docs/_autosummary/pya.ugen.rst
@@ -0,0 +1,32 @@
+pya.ugen
+========
+
+.. automodule:: pya.ugen
+
+
+
+
+
+
+
+ .. rubric:: Functions
+
+ .. autosummary::
+
+ get_num_of_rows
+
+
+
+
+
+ .. rubric:: Classes
+
+ .. autosummary::
+
+ Ugen
+
+
+
+
+
+
diff --git a/docs/_autosummary/pya.version.rst b/docs/_autosummary/pya.version.rst
new file mode 100644
index 00000000..79dcd917
--- /dev/null
+++ b/docs/_autosummary/pya.version.rst
@@ -0,0 +1,20 @@
+pya.version
+===========
+
+.. automodule:: pya.version
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/api.rst b/docs/api.rst
new file mode 100644
index 00000000..f6eec178
--- /dev/null
+++ b/docs/api.rst
@@ -0,0 +1,8 @@
+API Reference
+=============
+
+.. autosummary::
+ :toctree: _autosummary
+ :recursive:
+
+ pya
diff --git a/docs/conf.py b/docs/conf.py
index b760e30b..d9a8f9f6 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -30,17 +30,31 @@
# 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.napoleon',
- 'sphinx_mdinclude',
- 'autoapi.extension']
+extensions = [
+ 'sphinx.ext.napoleon',
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.autosummary',
+ 'myst_parser',
+]
+
+# Napoleon settings
+napoleon_numpy_docstring = True
+napoleon_google_docstring = False
+
+# Autodoc settings
+autodoc_default_options = {
+ 'members': True,
+ 'undoc-members': True,
+ 'show-inheritance': True,
+}
source_suffix = ['.rst', '.md']
-autoapi_type = 'python'
-autoapi_dirs = ['../pya']
-autoapi_ignore = ['*/version.py']
-autoapi_add_toctree_entry = False
+
autosectionlabel_prefix_document = True
+# Autosummary settings
+autosummary_generate = True # auto-generates stub RST files
+
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -61,11 +75,3 @@
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
-
-
-def setup(app):
- config = {
- # 'url_resolver': lambda url: github_doc_root + url,
- 'auto_toc_tree_section': 'Contents',
- 'enable_eval_rst': True,
- }
diff --git a/docs/index.rst b/docs/index.rst
index e56f79ce..1b7ac1af 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,12 +1,13 @@
.. toctree::
:maxdepth: 2
-.. mdinclude:: ../README.md
+ readme
+ api
Indices and tables
==================
-* :doc:`API Reference `
+* :doc:`API Reference `
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
diff --git a/docs/readme.rst b/docs/readme.rst
new file mode 100644
index 00000000..339dc8f4
--- /dev/null
+++ b/docs/readme.rst
@@ -0,0 +1,2 @@
+.. include:: ../README.md
+ :parser: myst_parser.sphinx_
diff --git a/examples/pya-example-Amfcc.ipynb b/examples/pya-example-Amfcc.ipynb
index b71d0dd3..e511040f 100644
--- a/examples/pya-example-Amfcc.ipynb
+++ b/examples/pya-example-Amfcc.ipynb
@@ -11,95 +11,44 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# This part only makes sure that the repository version of pya is used for this notebook ...\n",
- "import os, sys, inspect, io\n",
+ "import inspect\n",
+ "import os\n",
+ "import sys\n",
"\n",
"cmd_folder = os.path.realpath(\n",
" os.path.dirname(\n",
- " os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0])))\n",
+ " os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0])\n",
+ " )\n",
+ ")\n",
"\n",
"if cmd_folder not in sys.path:\n",
" sys.path.insert(0, cmd_folder)\n",
"\n",
"# ... the part relevant for pya usage starts here\n",
- "from pya import Asig, Amfcc"
+ "from pya import Asig"
]
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Asig('word'): 1 x 87040 @ 44100Hz = 1.974s cn=['0']"
- ]
- },
- "execution_count": 2,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"# Load a sample audio\n",
- "aword = Asig(\"samples/sonification.wav\", label='word')\n",
+ "aword = Asig(\"samples/sonification.wav\", label=\"word\")\n",
"aword.plot()"
]
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[ -9.17548107 -15.13285146 5.73257773 ... -3.2166908 -10.76164443\n",
- " 1.32956441]\n",
- " [ -9.14692637 -16.17379626 5.54862945 ... -7.32108897 -11.65220551\n",
- " -0.88169502]\n",
- " [ -9.18433397 -13.87876107 6.81787026 ... 2.94985548 -14.60185015\n",
- " -4.87923131]\n",
- " ...\n",
- " [ -9.07456594 -15.13518397 11.04234605 ... -1.4942507 -5.81623361\n",
- " -1.79442066]\n",
- " [ -9.03225387 -13.53938344 11.99418285 ... 4.10384531 1.00526457\n",
- " 1.34213652]\n",
- " [ -9.28960578 -14.93989893 8.99820526 ... -1.09119139 -10.48636787\n",
- " 3.15961457]]\n"
- ]
- },
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"amfcc = aword.to_mfcc()\n",
"amfcc.plot()\n",
@@ -162,29 +111,11 @@
" An array of mel filters\n",
" cepstra : numpy.ndarray\n",
" An array of the MFCC coeffcient, size: nframes x ncep\n",
- "\"\"\"\n"
+ "\"\"\""
]
}
],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.7.7"
- }
- },
+ "metadata": {},
"nbformat": 4,
"nbformat_minor": 4
}
diff --git a/examples/pya-examples.ipynb b/examples/pya-examples.ipynb
index 08df7a9d..04639bfe 100644
--- a/examples/pya-examples.ipynb
+++ b/examples/pya-examples.ipynb
@@ -15,7 +15,8 @@
"outputs": [],
"source": [
"# This part only makes sure that the repository version of pya is used for this notebook ...\n",
- "import os, sys, inspect, io\n",
+ "import os\n",
+ "import sys\n",
"\n",
"cmd_folder = os.path.abspath(sys.path[0] + \"/../\")\n",
"\n",
@@ -23,8 +24,9 @@
" sys.path.insert(0, cmd_folder)\n",
"\n",
"# ... the part relevant for pya usage starts here\n",
- "from pya import *\n",
- "from pyamapping import dbamp, ampdb"
+ "from pyamapping import ampdb\n",
+ "\n",
+ "from pya import *"
]
},
{
@@ -64,7 +66,7 @@
"metadata": {},
"outputs": [],
"source": [
- "# To check all available devices \n",
+ "# To check all available devices\n",
"device_info();"
]
},
@@ -76,14 +78,16 @@
"source": [
"# header - imports\n",
"import time\n",
+ "\n",
+ "import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import scipy\n",
- "import matplotlib.pyplot as plt\n",
- "from ipywidgets import interact, fixed, widgets\n",
+ "from ipywidgets import interact\n",
+ "\n",
"# plot graphs right into the notebook\n",
"%matplotlib inline \n",
"# for dedicated GUI windows with Qt5, uncomment the following line:\n",
- "# %matplotlib qt5 "
+ "# %matplotlib qt5"
]
},
{
@@ -205,7 +209,7 @@
"metadata": {},
"outputs": [],
"source": [
- "asnap = Asig(\"samples/snap.wav\", label='snap')\n",
+ "asnap = Asig(\"samples/snap.wav\", label=\"snap\")\n",
"asnap"
]
},
@@ -231,7 +235,7 @@
"metadata": {},
"outputs": [],
"source": [
- "aping = Asig(\"samples/ping.mp3\", label='ping')\n",
+ "aping = Asig(\"samples/ping.mp3\", label=\"ping\")\n",
"aping"
]
},
@@ -251,7 +255,7 @@
"outputs": [],
"source": [
"# load a speech sample\n",
- "aword = Asig(\"samples/sonification.wav\", label='word')\n",
+ "aword = Asig(\"samples/sonification.wav\", label=\"word\")\n",
"aword"
]
},
@@ -271,7 +275,7 @@
"outputs": [],
"source": [
"# create a signal from data\n",
- "anoise = Asig(np.random.randn(44100), sr=44100, label='noise')\n",
+ "anoise = Asig(np.random.randn(44100), sr=44100, label=\"noise\")\n",
"anoise"
]
},
@@ -281,8 +285,8 @@
"metadata": {},
"outputs": [],
"source": [
- "# record() helper function is currently removed until future release. \n",
- "# Use Arecorder() for recording. \n",
+ "# record() helper function is currently removed until future release.\n",
+ "# Use Arecorder() for recording.\n",
"# # record an audio signal, follow with a normalization\n",
"# arec = Asig(record(2.0), label='rec').norm()"
]
@@ -294,7 +298,7 @@
"outputs": [],
"source": [
"# create 2s silence at default sr\n",
- "Asig(2.0, label='sonification')"
+ "Asig(2.0, label=\"sonification\")"
]
},
{
@@ -303,8 +307,10 @@
"metadata": {},
"outputs": [],
"source": [
- "# create a 44100 x 4 signal at 22050 sr, give the channel names cn \n",
- "asignal = Asig(44100, sr=44100//2, label='silence', channels=4, cn=['a', 'b', 'c', 'd'])"
+ "# create a 44100 x 4 signal at 22050 sr, give the channel names cn\n",
+ "asignal = Asig(\n",
+ " 44100, sr=44100 // 2, label=\"silence\", channels=4, cn=[\"a\", \"b\", \"c\", \"d\"]\n",
+ ")"
]
},
{
@@ -320,7 +326,7 @@
"metadata": {},
"outputs": [],
"source": [
- "asignal.sig # signal array "
+ "asignal.sig # signal array"
]
},
{
@@ -329,7 +335,7 @@
"metadata": {},
"outputs": [],
"source": [
- "asignal.samples # nr of samples on each channels"
+ "asignal.samples # nr of samples on each channels"
]
},
{
@@ -347,7 +353,7 @@
"metadata": {},
"outputs": [],
"source": [
- "asignal.sr # sampling rate"
+ "asignal.sr # sampling rate"
]
},
{
@@ -356,7 +362,7 @@
"metadata": {},
"outputs": [],
"source": [
- "asignal.label # asig label "
+ "asignal.label # asig label"
]
},
{
@@ -365,7 +371,7 @@
"metadata": {},
"outputs": [],
"source": [
- "asignal.cn # channel name list"
+ "asignal.cn # channel name list"
]
},
{
@@ -489,11 +495,11 @@
"source": [
"print(\"Length in second: \", asnap.get_duration(), aword.get_duration())\n",
"try:\n",
- " (asnap + aword).play() \n",
+ " (asnap + aword).play()\n",
"except ValueError:\n",
" print(\"asnap and aword are different in size\")\n",
"\n",
- "(asnap.x + aword).play() # same as (asnap.extend + aword).play() \n"
+ "(asnap.x + aword).play() # same as (asnap.extend + aword).play()"
]
},
{
@@ -525,10 +531,9 @@
"metadata": {},
"outputs": [],
"source": [
- "import time\n",
"t0 = time.time()\n",
- "asnap.play(onset=t0+0.75)\n",
- "aword.play(onset=t0+0.1)"
+ "asnap.play(onset=t0 + 0.75)\n",
+ "aword.play(onset=t0 + 0.1)"
]
},
{
@@ -562,7 +567,7 @@
"metadata": {},
"outputs": [],
"source": [
- "aword.plot(lambda x: ampdb(abs(x)+0.01), lw=0.5, color=\"r\") # try also with arg 'db'"
+ "aword.plot(lambda x: ampdb(abs(x) + 0.01), lw=0.5, color=\"r\") # try also with arg 'db'"
]
},
{
@@ -571,8 +576,8 @@
"metadata": {},
"outputs": [],
"source": [
- "aword.plot(lambda x: ampdb(abs(x)*1e2+1), lw=0.15)\n",
- "aword.plot(lambda x: 100*abs(x)**2, color='red', lw=0.25)"
+ "aword.plot(lambda x: ampdb(abs(x) * 1e2 + 1), lw=0.15)\n",
+ "aword.plot(lambda x: 100 * abs(x) ** 2, color=\"red\", lw=0.25)"
]
},
{
@@ -599,7 +604,7 @@
"metadata": {},
"outputs": [],
"source": [
- "aword.play(1.)"
+ "aword.play(1.0)"
]
},
{
@@ -609,8 +614,10 @@
"outputs": [],
"source": [
"# demonstrate plot() and play() daisy-chained and subsequent access to the _ dict\n",
- "asnap.plot(marker='o', mfc='r', ms=7, lw=0.1).play(server=s)._['plot'][0].set_markevery((700, 200))\n",
- "plt.xlim(0, 0.2);\n",
+ "asnap.plot(marker=\"o\", mfc=\"r\", ms=7, lw=0.1).play(server=s)._[\"plot\"][0].set_markevery(\n",
+ " (700, 200)\n",
+ ")\n",
+ "plt.xlim(0, 0.2)\n",
"asnap._"
]
},
@@ -639,7 +646,9 @@
"outputs": [],
"source": [
"b = Ugen().sine(freq=100, sr=1000, dur=0.6).fade_in(0.3).fade_out(0.2)\n",
- "b *= 0.5+0.2*np.sin(2*np.pi*15*b.get_times()) # AM, note that you can directly apply arithemetics to Asig rather than Asig.sig\n",
+ "b *= 0.5 + 0.2 * np.sin(\n",
+ " 2 * np.pi * 15 * b.get_times()\n",
+ ") # AM, note that you can directly apply arithemetics to Asig rather than Asig.sig\n",
"b.plot().norm().play()\n",
"# note that repeated cell executions changes signal more and more"
]
@@ -677,7 +686,9 @@
"source": [
"def test_stride(stride=2):\n",
" aword[0:40000:stride].play()\n",
- "interact(test_stride, stride=(1,20,1));"
+ "\n",
+ "\n",
+ "interact(test_stride, stride=(1, 20, 1));"
]
},
{
@@ -706,10 +717,10 @@
"outputs": [],
"source": [
"# create a 4-channel sine\n",
- "amultichan = Ugen().sine(freq=200, sr=2000, channels=4, cn=['a','b','c','d']) \n",
+ "amultichan = Ugen().sine(freq=200, sr=2000, channels=4, cn=[\"a\", \"b\", \"c\", \"d\"])\n",
"\n",
"# create a 1-channel sawtooth\n",
- "amono = Ugen().sawtooth(freq=40, sr=2000, channels=1) "
+ "amono = Ugen().sawtooth(freq=40, sr=2000, channels=1)"
]
},
{
@@ -719,8 +730,8 @@
"outputs": [],
"source": [
"# use index list to create a subset of samples\n",
- "amono[[3, 30, 300]].sig \n",
- "amultichan[[3, 30, 300], :].sig "
+ "amono[[3, 30, 300]].sig\n",
+ "amultichan[[3, 30, 300], :].sig"
]
},
{
@@ -730,8 +741,8 @@
"outputs": [],
"source": [
"# channel selection based on channel name cn, using a list\n",
- "amultichan[:, ['a']]\n",
- "amultichan[:, ['a', 'd']]"
+ "amultichan[:, [\"a\"]]\n",
+ "amultichan[:, [\"a\", \"d\"]]"
]
},
{
@@ -750,8 +761,10 @@
"outputs": [],
"source": [
"# You can use a dictionary for time slicing. {start:end}\n",
- "amultichan[{0.2:0.6}] # from 0.2 to 0.6 second\n",
- "amono[{0.2:-0.4}] # This results the same as above, start at 0.2, end at 0.4 to the end. "
+ "amultichan[{0.2: 0.6}] # from 0.2 to 0.6 second\n",
+ "amono[\n",
+ " {0.2: -0.4}\n",
+ "] # This results the same as above, start at 0.2, end at 0.4 to the end."
]
},
{
@@ -760,7 +773,7 @@
"metadata": {},
"outputs": [],
"source": [
- "amultichan[0:amultichan.samples:4, ['a', 'c']] # a rough down-sampling"
+ "amultichan[0 : amultichan.samples : 4, [\"a\", \"c\"]] # a rough down-sampling"
]
},
{
@@ -793,8 +806,10 @@
"metadata": {},
"outputs": [],
"source": [
- "# create some test signals \n",
- "amultichan = Ugen().sine(freq=200, sr=2000, channels=4, cn=['a','b','c','d']) # create a 4-channel sine\n",
+ "# create some test signals\n",
+ "amultichan = Ugen().sine(\n",
+ " freq=200, sr=2000, channels=4, cn=[\"a\", \"b\", \"c\", \"d\"]\n",
+ ") # create a 4-channel sine\n",
"amono = Ugen().sawtooth(freq=40, sr=2000, channels=1) # create a 1-channel sawtooth\n",
"anoise = Ugen().noise(sr=2000, channels=1) # create a 1-channel white noise"
]
@@ -813,8 +828,10 @@
"outputs": [],
"source": [
"amono[3:6] = [1.0, -1.0, 0.5] # set three samples explicitly with values\n",
- "amono[20:40] = np.zeros(20) # set 20 samples to zero\n",
- "amono[{0.5: 0.7}] = anoise[{0.2: 0.4}] # set a 200ms-segment to noise, requiring length match"
+ "amono[20:40] = np.zeros(20) # set 20 samples to zero\n",
+ "amono[{0.5: 0.7}] = anoise[\n",
+ " {0.2: 0.4}\n",
+ "] # set a 200ms-segment to noise, requiring length match"
]
},
{
@@ -841,7 +858,7 @@
"try:\n",
" amono[-10:] = np.ones(20) # This won't not work and raise the exception\n",
"except ValueError:\n",
- " amono.b[-10:] = np.arange(20) # The first 10 elements will be assigned. \n",
+ " amono.b[-10:] = np.arange(20) # The first 10 elements will be assigned.\n",
"amono[-10:].sig"
]
},
@@ -866,11 +883,13 @@
"metadata": {},
"outputs": [],
"source": [
- "a = Asig(0.8, sr=1000, channels=4, cn=['a', 'b', 'c', 'd'], label='x-demosig')\n",
+ "a = Asig(0.8, sr=1000, channels=4, cn=[\"a\", \"b\", \"c\", \"d\"], label=\"x-demosig\")\n",
"b = Ugen().sine(freq=100, sr=1000, dur=0.6).fade_in(0.3).fade_out(0.2)\n",
- "a.x[:, 'a'] = 0.2 * b # no need to extend as len(src) 0:
nframes, ncoeff = np.shape(cepstra)
n = np.arange(ncoeff)
- lift = 1 + (L / 2.) * np.sin(np.pi * n / L)
+ lift = 1 + (L / 2.0) * np.sin(np.pi * n / L)
return lift * cepstra
else:
# values of L <= 0, do nothing
return cepstra
- def plot(self, show_bar: bool = True, offset: int = 0, scale: float = 1.,
- xlim: Optional[float] = None, ylim: Optional[float] = None,
- x_as_time: bool = True, nxlabel: int = 8, ax=None, **kwargs):
+ def plot(
+ self,
+ show_bar: bool = True,
+ offset: int = 0,
+ scale: float = 1.0,
+ xlim: Optional[float] = None,
+ ylim: Optional[float] = None,
+ x_as_time: bool = True,
+ nxlabel: int = 8,
+ ax=None,
+ **kwargs,
+ ):
"""Plot Amfcc.features via matshow, x is frames/time, y is the MFCCs
Parameters
@@ -332,7 +359,8 @@ def plot(self, show_bar: bool = True, offset: int = 0, scale: float = 1.,
show_bar : bool, optional
Default is True, show colorbar.
offset: int
- It is the spacing between channel, without setting it every channel will be overlayed onto each other.
+ It is the spacing between channel,
+ without setting it every channel will be overlayed onto each other.
scale: float
Visual scaling for improve visibility
xlim: float, optional
@@ -343,21 +371,32 @@ def plot(self, show_bar: bool = True, offset: int = 0, scale: float = 1.,
The amountt of labels on the x axis. Default is 8 .
"""
if self.channels > 1:
- warn("Multichannel mfcc is not yet implemented. Please use "
- "mono signal for now, no plot is made")
+ warn(
+ "Multichannel mfcc is not yet implemented. Please use "
+ "mono signal for now, no plot is made"
+ )
return self
- im, ax = basicplot(self.cepstra.T, None,
- channels=self.channels,
- cn=self.cn, offset=offset, scale=scale,
- ax=ax, typ='mfcc', show_bar=show_bar,
- xlabel='time', xlim=xlim, ylim=ylim, **kwargs)
+ im, ax = basicplot(
+ self.cepstra.T,
+ None,
+ channels=self.channels,
+ cn=self.cn,
+ offset=offset,
+ scale=scale,
+ ax=ax,
+ typ="mfcc",
+ show_bar=show_bar,
+ xlabel="time",
+ xlim=xlim,
+ ylim=ylim,
+ **kwargs,
+ )
self.im = im
xticks = np.linspace(0, self.nframes, nxlabel, dtype=int)
ax.set_xticks(xticks)
# ax.set_("MFCC Coefficient")
if x_as_time:
- xlabels = np.round(np.linspace(0, self.duration, nxlabel),
- decimals=2)
+ xlabels = np.round(np.linspace(0, self.duration, nxlabel), decimals=2)
# Replace x ticks with timestamps
ax.set_xticklabels(xlabels)
ax.xaxis.tick_bottom()
diff --git a/pya/arecorder.py b/pya/arecorder.py
index 5676d44f..c0f9c8f1 100644
--- a/pya/arecorder.py
+++ b/pya/arecorder.py
@@ -5,10 +5,10 @@
from typing import Optional, Union
import numpy as np
-from . import Asig
-from . import Aserver
from pyamapping import db_to_amp
+from pya.aserver import Aserver
+from pya.asig import Asig
_LOGGER = logging.getLogger(__name__)
_LOGGER.addHandler(logging.NullHandler())
@@ -35,16 +35,26 @@ class Arecorder(Aserver):
... ar.stop()
"""
- def __init__(self, sr: int = 44100, bs: int = 256, device: Optional[int] = None,
- channels: Optional[int] = None, backend=None, **kwargs):
- super().__init__(sr=sr, bs=bs, device=device,
- backend=backend, **kwargs)
+ def __init__(
+ self,
+ sr: int = 44100,
+ bs: int = 256,
+ device: Optional[int] = None,
+ channels: Optional[int] = None,
+ backend=None,
+ **kwargs,
+ ):
+ super().__init__(sr=sr, bs=bs, device=device, backend=backend, **kwargs)
self.record_buffer = []
self.recordings = [] # store recorded Asigs, time stamp in label
self._recording = False
self._record_all = True
self.tracks = slice(None)
- self._device = self.backend.get_default_input_device_info()['index'] if device is None else device
+ self._device = (
+ self.backend.get_default_input_device_info()["index"]
+ if device is None
+ else device
+ )
self._channels = channels or self.max_in_chn
self.gains = np.ones(self._channels)
@@ -61,7 +71,9 @@ def channels(self, val: int):
raise ValueError(f"AServer: channels {val} > max {self.max_in_chn}")
self._channels = val
- def set_tracks(self, tracks: Union[list, np.ndarray], gains: Union[list, np.ndarray]):
+ def set_tracks(
+ self, tracks: Union[list, np.ndarray], gains: Union[list, np.ndarray]
+ ):
"""Define the number of track to be recorded and their gains.
parameters
@@ -94,20 +106,28 @@ def boot(self):
# self.block_cnt = 0
self.record_buffer = []
self._recording = False
- self.stream = self.backend.open(rate=self.sr, channels=self.channels, frames_per_buffer=self.bs,
- input_device_index=self.device, output_flag=False,
- input_flag=True, stream_callback=self._recorder_callback)
+ self.stream = self.backend.open(
+ rate=self.sr,
+ channels=self.channels,
+ frames_per_buffer=self.bs,
+ input_device_index=self.device,
+ output_flag=False,
+ input_flag=True,
+ stream_callback=self._recorder_callback,
+ )
_LOGGER.info("Server Booted")
return self
def _recorder_callback(self, in_data, frame_count, time_info, flag):
- """Callback function during streaming. """
+ """Callback function during streaming."""
# self.block_cnt += 1
if self._recording:
sigar = np.frombuffer(in_data, dtype=self.backend.dtype)
# (chunk length, chns)
data_float = np.reshape(sigar, (len(sigar) // self.channels, self.channels))
- data_float = data_float[:, self.tracks] * self.gains # apply channel selection and gains.
+ data_float = (
+ data_float[:, self.tracks] * self.gains
+ ) # apply channel selection and gains.
# if not self._record_all
self.record_buffer.append(data_float)
# E = 10 * np.log10(np.mean(data_float ** 2)) # energy in dB
@@ -137,6 +157,6 @@ def __repr__(self):
if self.stream:
state = self.stream.is_active()
msg = f"""Arecorder: sr: {self.sr}, blocksize: {self.bs}, Stream Active: {state}
- Input: {self.device_dict['name']}, Index: {self.device_dict['index']}
+ Input: {self.device_dict["name"]}, Index: {self.device_dict["index"]}
"""
return msg
diff --git a/pya/aserver.py b/pya/aserver.py
index 223d944b..ffc5b5c5 100644
--- a/pya/aserver.py
+++ b/pya/aserver.py
@@ -1,4 +1,3 @@
-from .helper.backend import determine_backend
import copy
import logging
import time
@@ -7,13 +6,15 @@
import numpy as np
+from .helper.backend import determine_backend
_LOGGER = logging.getLogger(__name__)
_LOGGER.addHandler(logging.NullHandler())
class Aserver:
- """Pya audio server
+ """
+ Pya audio server
Based on pyaudio, works as a FIFO style audio stream pipeline,
allowing Asig.play() to send audio segement into the stream.
@@ -27,7 +28,8 @@ class Aserver:
>>> asine = Ugen().sine()
>>> asine.play(server=ser)
Asig('sine'): 1 x 44100 @ 44100Hz = 1.000s cn=['0']
- >>> ser.quit() # Important to call quit() to close the stream when you are done. Or use context manager.
+ >>> ser.quit() # Important to call quit() to close the stream when you are done.
+ Or use context manager.
"""
default = None # that's the default Aserver if Asigs play via it
@@ -52,9 +54,15 @@ def shutdown_default_server():
else:
warn("Aserver:shutdown_default_server: no default_server to shutdown")
- def __init__(self, sr: int = 44100, bs: Optional[int] = None,
- device: Optional[int] = None, channels: Optional[int] = None,
- backend=None, **kwargs):
+ def __init__(
+ self,
+ sr: int = 44100,
+ bs: Optional[int] = None,
+ device: Optional[int] = None,
+ channels: Optional[int] = None,
+ backend=None,
+ **kwargs,
+ ):
"""Aserver manages an pyaudio stream, using its aserver callback
to feed dispatched signals to output at the right time.
@@ -65,7 +73,7 @@ def __init__(self, sr: int = 44100, bs: Optional[int] = None,
bs : int
Override block size or buffer size set by chosen backend
device : int
- The device index based on pya.device_info(), default is None which will set
+ The device index based on pya.device_info(), default is None which will set
the default device from PyAudio
channels : int
number of channel, default is the max output channels of the device
@@ -85,12 +93,16 @@ def __init__(self, sr: int = 44100, bs: Optional[int] = None,
self.input_devices = []
self.output_devices = []
for i in range(self.backend.get_device_count()):
- if int(self.backend.get_device_info_by_index(i)['maxInputChannels']) > 0:
+ if int(self.backend.get_device_info_by_index(i)["maxInputChannels"]) > 0:
self.input_devices.append(self.backend.get_device_info_by_index(i))
- if int(self.backend.get_device_info_by_index(i)['maxOutputChannels']) > 0:
+ if int(self.backend.get_device_info_by_index(i)["maxOutputChannels"]) > 0:
self.output_devices.append(self.backend.get_device_info_by_index(i))
- self._device = self.backend.get_default_output_device_info()['index'] if device is None else device
+ self._device = (
+ self.backend.get_default_output_device_info()["index"]
+ if device is None
+ else device
+ )
self._channels = channels or self.max_out_chn
self.gain = 1.0
@@ -125,11 +137,11 @@ def device_dict(self):
@property
def max_out_chn(self) -> int:
- return int(self.device_dict['maxOutputChannels'])
+ return int(self.device_dict["maxOutputChannels"])
@property
def max_in_chn(self) -> int:
- return int(self.device_dict['maxInputChannels'])
+ return int(self.device_dict["maxInputChannels"])
@property
def is_active(self) -> bool:
@@ -141,30 +153,47 @@ def device(self):
@device.setter
def device(self, val):
- self._device = val if val is not None else self.backend.get_default_output_device_info()['index']
+ self._device = (
+ val
+ if val is not None
+ else self.backend.get_default_output_device_info()["index"]
+ )
if self.max_out_chn < self.channels:
- warn(f"Aserver: warning: {self.channels}>{self.max_out_chn} channels requested - truncated.")
+ warn(
+ f"Aserver: warning: {self.channels}>{self.max_out_chn} channels requested - truncated." # noqa E501
+ )
self.channels = self.max_out_chn
def __repr__(self):
msg = f"""AServer: sr: {self.sr}, blocksize: {self.bs},
- Stream Active: {self.is_active}, Device: {self.device_dict['name']}, Index: {self.device_dict['index']}"""
+ Stream Active: {self.is_active}, Device: {self.device_dict["name"]},
+ Index: {self.device_dict["index"]}
+ """
return msg
def get_devices(self, verbose: bool = False):
"""Return (and optionally print) available input and output device"""
if verbose:
print("Input Devices: ")
- [print(f"Index: {i['index']}, Name: {i['name']}, Channels: {i['maxInputChannels']}")
- for i in self.input_devices]
+ [
+ print(
+ f"Index: {i['index']}, Name: {i['name']}, Channels: {i['maxInputChannels']}" # noqa E501
+ )
+ for i in self.input_devices
+ ]
print("Output Devices: ")
- [print(f"Index: {i['index']}, Name: {i['name']}, Channels: {i['maxOutputChannels']}")
- for i in self.output_devices]
+ [
+ print(
+ f"Index: {i['index']}, Name: {i['name']}, Channels: {i['maxOutputChannels']}" # noqa E501
+ )
+ for i in self.output_devices
+ ]
return self.input_devices, self.output_devices
def set_device(self, idx: int, reboot: bool = True):
- """Set audio device, an alternative way is to direct set the device property, i.e. Aserver.device = 1,
- but that will not reboot the server.
+ """
+ Set audio device, an alternative way is to direct set the device property,
+ i.e. Aserver.device = 1, but that will not reboot the server.
Parameters
----------
@@ -192,11 +221,15 @@ def boot(self):
self.boot_time = time.time()
self.block_time = self.boot_time
self.block_cnt = 0
- self.stream = self.backend.open(channels=self.channels, rate=self.sr,
- input_flag=False, output_flag=True,
- frames_per_buffer=self.bs,
- output_device_index=self.device,
- stream_callback=self._play_callback)
+ self.stream = self.backend.open(
+ channels=self.channels,
+ rate=self.sr,
+ input_flag=False,
+ output_flag=True,
+ frames_per_buffer=self.bs,
+ output_device_index=self.device,
+ stream_callback=self._play_callback,
+ )
self._is_active = self.stream.is_active()
_LOGGER.info("Server Booted")
return self
@@ -242,7 +275,9 @@ def play(self, asig, onset: Union[int, float] = 0, out: int = 0, **kwargs):
asig = copy.copy(asig)
asig.sig = asig.sig.astype(self.backend.dtype)
# copy only relevant channels...
- nchn = min(asig.channels, self.channels - out) # max number of copyable channels
+ nchn = min(
+ asig.channels, self.channels - out
+ ) # max number of copyable channels
# in: [:nchn] out: [out:out+nchn]
if id(asig) == sigid:
asig = copy.copy(asig)
@@ -254,7 +289,7 @@ def play(self, asig, onset: Union[int, float] = 0, out: int = 0, **kwargs):
self.srv_asigs.insert(idx, asig)
self.srv_curpos.insert(idx, 0)
self.srv_outs.insert(idx, out)
- if 'block' in kwargs and kwargs['block']:
+ if "block" in kwargs and kwargs["block"]:
if onset > 0: # here really omset and not rt_onset!
_LOGGER.warning("blocking inactive with play(onset>0)")
else:
@@ -294,11 +329,11 @@ def _play_callback(self, in_data, frame_count, time_info, flag):
io0 = int((t - tnow) * self.sr)
else:
io0 = 0
- tmpsig = a.sig[c:c + self.bs - io0]
+ tmpsig = a.sig[c : c + self.bs - io0]
n, nch = tmpsig.shape
out = self.srv_outs[i]
# .reshape(n, nch) not needed as moved to play
- data[io0:io0 + n, out:out + nch] += tmpsig
+ data[io0 : io0 + n, out : out + nch] += tmpsig
self.srv_curpos[i] += n
if self.srv_curpos[i] >= a.samples:
dellist.append(i) # store for deletion
@@ -324,9 +359,9 @@ def __exit__(self, exc_type, exc_value, traceback):
def __del__(self):
"""Backup cleanup, only if context manager wasn't used"""
- if hasattr(self, 'stream') and self.stream is not None:
+ if hasattr(self, "stream") and self.stream is not None:
try:
self.quit()
self.backend.terminate()
- except:
+ except Exception:
pass # Ignore cleanup errors during shutdown
diff --git a/pya/asig.py b/pya/asig.py
index 820267fc..05ede9e6 100644
--- a/pya/asig.py
+++ b/pya/asig.py
@@ -1,28 +1,25 @@
-from itertools import compress
-import numbers
import logging
-from typing import Iterable
-from typing import Optional
-from typing import Union
+import numbers
+from itertools import compress
+from typing import Iterable, Optional, Union
from warnings import warn
-import numpy as np
import matplotlib.pyplot as plt
+import numpy as np
import scipy.interpolate
import scipy.signal
-from scipy.io import wavfile
-
from pyamapping import amp_to_db, db_to_amp, linlin
-from .helper import spectrum, audio_from_file, padding
-from .helper import basicplot
+from scipy.io import wavfile
+from .helper import audio_from_file, basicplot, padding, spectrum
_LOGGER = logging.getLogger(__name__)
_LOGGER.addHandler(logging.NullHandler())
class Asig:
- """Audio signal class.
+ """
+ Audio signal class.
Asig enables manipulation of audio signals in the style of numpy and more.
Asig offer functions for plotting (via matplotlib) and playing audio
(using the pya.Aserver class)
@@ -54,20 +51,29 @@ class Asig:
the .bound, .extend and .overwrite properties.
"""
- def __init__(self, sig: Union[str, int, float, np.ndarray], sr: int = 44100,
- label: str = "", channels: int = 1, cn: Optional[list] = None):
- """__init__ method
+ def __init__(
+ self,
+ sig: Union[str, int, float, np.ndarray],
+ sr: int = 44100,
+ label: str = "",
+ channels: int = 1,
+ cn: Optional[list] = None,
+ ):
+ """
+ Constructor method
Parameters
----------
sig: numpy.array or int or float or str
- This is a multiple type argument, which all results in Asig.sig being a numpy.array to
+ This is a multiple type argument,
+ which all results in Asig.sig being a numpy.array to
represent the audio signal.
numpy.array for audio signal,
str for filepath. Currently support two types of audio loader:
- 1) Standard library for .wav, .aiff, and 2) ffmpeg for other such as .mp3.
+ 1) Standard library for .wav, .aiff
+ 2) ffmpeg for other such as .mp3.
int create x samples of silence,
@@ -104,8 +110,7 @@ def __init__(self, sig: Union[str, int, float, np.ndarray], sr: int = 44100,
if channels == 1:
self.sig = np.zeros(int(sig * sr)).astype(self.dtype)
else:
- self.sig = np.zeros(
- (int(sig * sr), channels)).astype(self.dtype)
+ self.sig = np.zeros((int(sig * sr), channels)).astype(self.dtype)
else:
self.sig = np.array(sig).astype(self.dtype)
self.cn = cn
@@ -140,12 +145,10 @@ def cn(self, val):
if all(isinstance(x, str) for x in val):
self._cn = val
else:
- raise TypeError(
- "channel names cn need to be a list of string(s).")
+ raise TypeError("channel names cn need to be a list of string(s).")
else:
raise ValueError(
- "list size doesn't match channel numbers {}".format(
- self.channels)
+ "list size doesn't match channel numbers {}".format(self.channels)
)
@property
@@ -163,7 +166,8 @@ def dur(self) -> float:
return self.samples / self.sr
def save_wavfile(self, fname: str = "asig.wav", dtype: str = "float32"):
- """Save signal as .wav file, return self.
+ """
+ Save signal as .wav file, return self.
Parameters
----------
@@ -193,7 +197,8 @@ def _set_col_names(self):
raise TypeError("column names need to be a list of strings")
def __getitem__(self, index):
- """ Accessing array elements through slicing.
+ """
+ Accessing array elements through slicing.
* int, get signal row asig[4];
* slice, range and step slicing asig[4:40:2]
# from 4 to 40 every 2 samples;
@@ -260,8 +265,7 @@ def __getitem__(self, index):
stop = None
ridx = slice(start, stop, 1)
sr = self.sr
- _LOGGER.debug("Time slicing, start: %s, stop: %s",
- str(start), str(stop))
+ _LOGGER.debug("Time slicing, start: %s, stop: %s", str(start), str(stop))
else: # Dont think there is a usecase.
ridx = rindex
sr = self.sr
@@ -273,8 +277,7 @@ def __getitem__(self, index):
cidx = [self.col_name.get(s) for s in cindex]
if cidx is None:
_LOGGER.error("Input column names does not exist")
- cn_new = [self.cn[i]
- for i in cidx] if self.cn is not None else None
+ cn_new = [self.cn[i] for i in cidx] if self.cn is not None else None
elif isinstance(cindex[0], bool):
cidx = cindex
cn_new = list(compress(self.cn, cindex))
@@ -282,8 +285,7 @@ def __getitem__(self, index):
try:
cidx = list(cindex)
cn_new = (
- [self.cn[i]
- for i in cindex] if self.cn is not None else None
+ [self.cn[i] for i in cindex] if self.cn is not None else None
)
except (TypeError, ValueError):
cidx = slice(0, 0, 0)
@@ -314,8 +316,7 @@ def __getitem__(self, index):
if sig.ndim == 2 and sig.shape[1] == 1:
# Hot fix this to be consistent with bool slciing
if not isinstance(cindex[0], bool):
- _LOGGER.debug(
- "ndim is 2 and channel num is 1, performa np.squeeze")
+ _LOGGER.debug("ndim is 2 and channel num is 1, performa np.squeeze")
sig = np.squeeze(sig)
if isinstance(sig, numbers.Number):
_LOGGER.debug("signal is scalar, convert to array")
@@ -327,8 +328,10 @@ def __getitem__(self, index):
@property
def x(self):
- """Extend mode: this mode allows destination
- sig size in assignment to be extended through setitem"""
+ """
+ Extend mode: this mode allows destination
+ sig size in assignment to be extended through setitem
+ """
# Set setitem mode to extend
self.mix_mode = "extend"
return self
@@ -337,8 +340,10 @@ def x(self):
@property
def b(self):
- """Bound mode: this mode allows to truncate a source signal
- in assignment to a limited destination in setitem."""
+ """
+ Bound mode: this mode allows to truncate a source signal
+ in assignment to a limited destination in setitem.
+ """
# Set setitem mode to bound
self.mix_mode = "bound"
return self
@@ -347,15 +352,18 @@ def b(self):
@property
def o(self):
- """Overwrite mode: this mode cuts and replaces target
- selection by source signal on assignment via setitem"""
+ """
+ Overwrite mode: this mode cuts and replaces target
+ selection by source signal on assignment via setitem
+ """
self.mix_mode = "overwrite"
return self
overwrite = o
def __setitem__(self, index, value):
- """setitem: asig[index] = value. This allows all the methods from getitem:
+ """
+ setitem: asig[index] = value. This allows all the methods from getitem:
* numpy style slicing
* string/string_list for subsetting based on channel name
* time slicing (unit seconds) via dict.
@@ -496,24 +504,18 @@ def __setitem__(self, index, value):
dn = dshape[0] # ToDo: howto get that faster from ridx alone?
sn = src.shape[0]
if sn > dn:
- self.sig[final_index] = src[:dn] if len(
- dshape) == 1 else src[:dn, :]
+ self.sig[final_index] = src[:dn] if len(dshape) == 1 else src[:dn, :]
else:
- self.sig[final_index][:sn] = src if len(
- dshape) == 1 else src[:, :]
+ self.sig[final_index][:sn] = src if len(dshape) == 1 else src[:, :]
elif mode == "extend":
_LOGGER.debug("setitem extend mode")
if isinstance(ridx, list):
- _LOGGER.error(
- "Extend mode not available for row index list"
- )
+ _LOGGER.error("Extend mode not available for row index list")
return self
if isinstance(ridx, slice):
if ridx.step not in [1, None]:
- raise AttributeError(
- "Extend mode only available for step-1 slices"
- )
+ raise AttributeError("Extend mode only available for step-1 slices")
if ridx.stop is not None and ridx.stop < self.samples:
raise AttributeError(
"The current slice does not stop at the end of array."
@@ -523,8 +525,7 @@ def __setitem__(self, index, value):
dn = dshape[0]
sn = src.shape[0]
if sn <= dn: # same as bound, since src fits in
- self.sig[final_index][:sn] = np.broadcast_to(
- src, (sn,) + dshape[1:])
+ self.sig[final_index][:sn] = np.broadcast_to(src, (sn,) + dshape[1:])
elif sn > dn:
self.sig[final_index] = src[:dn]
# now extend by nn = sn-dn additional rows
@@ -542,8 +543,7 @@ def __setitem__(self, index, value):
nn = ridx.start + sn
self.sig = np.r_[
self.sig,
- np.zeros(
- (nn - self.sig.shape[0],) + self.sig.shape[1:]),
+ np.zeros((nn - self.sig.shape[0],) + self.sig.shape[1:]),
].astype(self.dtype)
if self.sig.ndim == 1:
self.sig[-sn:] = src
@@ -581,8 +581,9 @@ def __setitem__(self, index, value):
self.sig = sig # Update self.sig
return self
- def resample(self, target_sr: int = 44100, rate: float = 1., kind: str = "linear"):
- """Resample signal based on interpolation, can process multichannel signals.
+ def resample(self, target_sr: int = 44100, rate: float = 1.0, kind: str = "linear"):
+ """
+ Resample signal based on interpolation, can process multichannel signals.
Parameters
----------
@@ -599,8 +600,11 @@ def resample(self, target_sr: int = 44100, rate: float = 1., kind: str = "linear
Asig with resampled signal.
"""
times = np.arange(self.samples) / self.sr
- tsel = (np.arange(np.floor(self.samples / self.sr *
- target_sr / rate)) * rate / target_sr)
+ tsel = (
+ np.arange(np.floor(self.samples / self.sr * target_sr / rate))
+ * rate
+ / target_sr
+ )
if self.channels == 1:
interp_fn = scipy.interpolate.interp1d(
times,
@@ -611,12 +615,12 @@ def resample(self, target_sr: int = 44100, rate: float = 1., kind: str = "linear
fill_value=self.sig[-1],
)
return Asig(
- interp_fn(tsel), target_sr,
- label=self.label + "_resampled", cn=self.cn
+ interp_fn(tsel), target_sr, label=self.label + "_resampled", cn=self.cn
)
else:
new_sig = np.ndarray(
- shape=(int(self.samples / self.sr * target_sr / rate), self.channels))
+ shape=(int(self.samples / self.sr * target_sr / rate), self.channels)
+ )
for i in range(self.channels):
interp_fn = scipy.interpolate.interp1d(
times,
@@ -629,8 +633,9 @@ def resample(self, target_sr: int = 44100, rate: float = 1., kind: str = "linear
new_sig[:, i] = interp_fn(tsel)
return Asig(new_sig, target_sr, label=self.label + "_resampled", cn=self.cn)
- def play(self, rate: float = 1., server=None, onset=0, channel=0, block=False):
- """Play Asig audio via Aserver, using Aserver.default (if existing)
+ def play(self, rate: float = 1.0, server=None, onset=0, channel=0, block=False):
+ """
+ Play Asig audio via Aserver, using Aserver.default (if existing)
kwargs are propagated to Aserver:play(onset=0, out=0)
Parameters
@@ -639,7 +644,8 @@ def play(self, rate: float = 1., server=None, onset=0, channel=0, block=False):
Playback rate (Default value = 1)
**kwargs : str
'server' : Aserver
- Set which server to play. e.g. s = Aserver(); s.boot(); asig.play(server=s)
+ Set which server to play.
+ e.g. s = Aserver(); s.boot(); asig.play(server=s)
Returns
-------
@@ -647,6 +653,7 @@ def play(self, rate: float = 1., server=None, onset=0, channel=0, block=False):
return self
"""
import pya.aserver
+
if server is None:
server = pya.aserver.Aserver.default
if rate == 1 and self.sr == server.sr:
@@ -657,10 +664,15 @@ def play(self, rate: float = 1., server=None, onset=0, channel=0, block=False):
return self
def shift_channel(self, shift: int = 0):
- """Shift signal to other channels. This is particular useful for assigning a mono signal to a specific channel.
- * shift = 0: does nothing as the same signal is being routed to the same position
- * shift > 0: shift channels of self.sig 'right', i.e. from [0,..channels-1] to channels [shift,shift+1,...]
- * shift < 0: shift channels of self.sig 'left', i.e. the first shift channels will be discarded.
+ """
+ Shift signal to other channels.
+ This is particular useful for assigning a mono signal to a specific channel.
+ * shift = 0: does nothing as the same signal
+ is being routed to the same position
+ * shift > 0: shift channels of self.sig 'right',
+ i.e. from [0,..channels-1] to channels [shift,shift+1,...]
+ * shift < 0: shift channels of self.sig 'left',
+ i.e. the first shift channels will be discarded.
Parameters
----------
@@ -682,7 +694,7 @@ def shift_channel(self, shift: int = 0):
if self.channels == 1:
new_sig[:, shift] = self.sig
elif shift > 0:
- new_sig[:, shift: (shift + self.channels)] = self.sig
+ new_sig[:, shift : (shift + self.channels)] = self.sig
elif shift < 0:
new_sig[:] = self.sig[:, -shift:]
if self.cn is None:
@@ -699,7 +711,8 @@ def shift_channel(self, shift: int = 0):
return Asig(new_sig, self.sr, label=self.label + "_routed", cn=new_cn)
def mono(self, blend: Optional[list] = None):
- """Mix channels to mono signal. Perform sig = np.sum(self.sig_copy * blend, axis=1)
+ """
+ Mix channels to mono signal. Perform sig = np.sum(self.sig_copy * blend, axis=1)
Parameters
----------
@@ -722,26 +735,37 @@ def mono(self, blend: Optional[list] = None):
raise AttributeError("len(blend) != self.channels")
else:
sig = np.sum(self.sig * blend, axis=1)
- col_names = [
- self.cn[np.argmax(blend)]] if self.cn is not None else None
+ col_names = [self.cn[np.argmax(blend)]] if self.cn is not None else None
return Asig(sig, self.sr, label=self.label + "_blended", cn=col_names)
def stereo(self, blend: Optional[list] = None):
- """Blend all channels of the signal to stereo. Applicable for any single-/ or multi-channel Asig.
+ """
+ Blend all channels of the signal to stereo.
+ Applicable for any single-/ or multi-channel Asig.
Parameters
----------
blend : list or None
- Usage: For mono, blend=(g1, g2), the channel will be broadcated to left, right with g1, g2 gains.
+ Usage: For mono, blend=(g1, g2),
+ the channel will be broadcated to left, right with g1, g2 gains.
+
For stereo signal, blend=(g1, g2), each channel is gain adjusted by g1, g2.
- For multichannel: blend = [[list of gains for left channel], [list of gains for right channel]]
- Default value = None, resulting in equal distribution to left and right channel
+
+ For multichannel:
+ blend = [
+ [list of gains for left channel],
+ [list of gains for right channel]
+ ]
+
+ Default value = None,
+ resulting in equal distribution to left and right channel
Example
-------
asig[:,['c1','c2','c3']].stereo[[1, 0.707, 0], [0, 0.707, 1]]
mixes channel 'c1' to left, 'c2' to center and 'c3' to right channel
- of a new stereo asig. Note that for equal loudness left**2+right**2=1 should be used
+ of a new stereo asig.
+ Note that for equal loudness left**2+right**2=1 should be used
Returns
-------
@@ -766,9 +790,10 @@ def stereo(self, blend: Optional[list] = None):
left_sig = np.sum(self.sig * left, axis=1)
right_sig = np.sum(self.sig * right, axis=1)
else:
- msg = """For signal channels > 2, argument blend should be a tuple of two lists,
- each list contains the gain for each channel to be mixed.
- """
+ msg = """
+ For signal channels > 2, argument blend should be a tuple of two lists,
+ each list contains the gain for each channel to be mixed.
+ """
raise AttributeError(msg)
sig = np.stack((left_sig, right_sig), axis=1)
@@ -785,7 +810,8 @@ def rewire(self, dic):
Example
-------
- {(0, 1): 0.2, (5, 0): 0.4}: rewire channel 0 to 1 with gain 0.2, and 5 to 1 with gain 2
+ {(0, 1): 0.2, (5, 0): 0.4}:
+ rewire channel 0 to 1 with gain 0.2, and 5 to 1 with gain 2
leaving other channels unmodified
Returns
@@ -808,7 +834,8 @@ def pan2(self, pan: float = 0.0):
Panning is based on constant power panning, see pan below
Behavior depends on nr of channels self.channels
* multi-channel signals (self.channels>2) are cut back to stereo and treated as
- * stereo signals (self.channels==2) are channelwise attenuated using cos(angle), sin(angle)
+ * stereo signals (self.channels==2)
+ are channelwise attenuated using cos(angle), sin(angle)
* mono signals (self.channels==1) result in stereo output asigs.
Parameters
@@ -865,7 +892,7 @@ def remove_DC(self):
sig = self.sig - np.mean(self.sig, 0)
return Asig(sig, sr=self.sr, label=self.label + "_DCfree", cn=self.cn)
- def norm(self, norm: float = 1., in_db: bool = False, dcflag: bool = False):
+ def norm(self, norm: float = 1.0, in_db: bool = False, dcflag: bool = False):
# ToDO add channel_wise argument . default True, currently it is the false.
"""Normalize signal
@@ -894,8 +921,11 @@ def norm(self, norm: float = 1., in_db: bool = False, dcflag: bool = False):
return Asig(sig, self.sr, label=self.label + "_normalised", cn=self.cn)
def gain(self, amp: Optional[float] = None, db: Optional[numbers.Number] = None):
- """Apply gain in amplitude or dB, only use one or the other arguments. Argument can be either a scalar
- or a list (to apply individual gain to each channel). The method returns a new asig with gain applied.
+ """
+ Apply gain in amplitude or dB, only use one or the other arguments.
+ Argument can be either a scalar or a list
+ (to apply individual gain to each channel).
+ The method returns a new asig with gain applied.
Parameters
----------
@@ -964,7 +994,7 @@ def plot(
if fn == "db":
def fn(x):
- return np.sign(x) * amp_to_db((abs(x) * 2 ** 16 + 1))
+ return np.sign(x) * amp_to_db((abs(x) * 2**16 + 1))
elif not callable(fn):
msg = "Asig.plot: fn is neither keyword nor function"
@@ -1002,7 +1032,10 @@ def get_times(self):
return np.linspace(0, (self.samples - 1) / self.sr, self.samples)
def __eq__(self, other):
- """Check if two asig objects have the same signal. But does not care about sr and others"""
+ """
+ Check if two asig objects have the same signal.
+ But does not care about sr and others
+ """
sig_eq = np.array_equal(self.sig, other.sig)
sr_eq = self.sr == other.sr
return sig_eq and sr_eq
@@ -1019,10 +1052,14 @@ def __repr__(self):
)
def __mul__(self, other):
- """Magic method for multiplying. You can either multiply a scalar or an Asig object. If muliplying an Asig,
- you don't always need to have same size arrays as audio signals may different in length. If mix_mode
- is set to 'bound' the size is fixed to respect self. If not, the result will respect to whichever the
- bigger array is."""
+ """
+ Magic method for multiplying.
+ You can either multiply a scalar or an Asig object.
+ If muliplying an Asig, you don't always need to have same size arrays
+ as audio signals may different in length. If mix_mode is set to 'bound' the size
+ is fixed to respect self. If not, the result will respect to whichever the
+ bigger array is.
+ """
selfsig = self.sig
othersig = other.sig if isinstance(other, Asig) else other
if isinstance(othersig, numbers.Number):
@@ -1060,13 +1097,16 @@ def __rmul__(self, other):
)
def __truediv__(self, other):
- """Magic method for division. You can either divide a scalar or an Asig object.
+ """
+ Magic method for division. You can either divide a scalar or an Asig object.
Use division with caution, audio signal is common to reach 0 or near,
avoid zero division or extremely large result.
- If dividing an Asig, you don't always need to have same size arrays as audio signals
- may different in length. If mix_mode is set to 'bound' the size is fixed to respect self.
- If not, the result will respect to whichever the bigger array is."""
+ If dividing an Asig, you don't always need to have same size arrays
+ as audio signals may different in length. If mix_mode is set to 'bound' the size
+ is fixed to respect self. If not, the result will respect to whichever
+ the bigger array is.
+ """
selfsig = self.sig
othersig = other.sig if isinstance(other, Asig) else other
if isinstance(othersig, numbers.Number):
@@ -1106,10 +1146,13 @@ def __rtruediv__(self, other):
)
def __add__(self, other):
- """Magic method for adding. You can either add a scalar or an Asig object. If adding an Asig,
- you don't always need to have same size arrays as audio signals may different in length. If mix_mode
- is set to 'bound' the size is fixed to respect self. If not, the result will respect to whichever the
- bigger array is."""
+ """
+ Magic method for adding. You can either add a scalar or an Asig object.
+ If adding an Asig, you don't always need to have same size arrays
+ as audio signals may different in length. If mix_mode is set to 'bound' the size
+ is fixed to respect self. If not, the result will respect to whichever the
+ bigger array is.
+ """
selfsig = self.sig
othersig = other.sig if isinstance(other, Asig) else other
if isinstance(othersig, numbers.Number): # When other is just a scalar
@@ -1146,10 +1189,13 @@ def __radd__(self, other):
return Asig(other + self.sig, self.sr, label=self.label + "_added", cn=self.cn)
def __sub__(self, other):
- """Magic method for subtraction. You can either minus a scalar or an Asig object. If subtracting an Asig,
- you don't always need to have same size arrays as audio signals may different in length. If mix_mode
- is set to 'bound' the size is fixed to respect self. If not, the result will respect to whichever the
- bigger array is."""
+ """
+ Magic method for subtraction. You can either minus a scalar or an Asig object.
+ If subtracting an Asig, you don't always need to have same size arrays
+ as audio signals may different in length. If mix_mode is set to 'bound' the size
+ is fixed to respect self. If not, the result will respect to whichever the
+ bigger array is.
+ """
selfsig = self.sig
othersig = other.sig if isinstance(other, Asig) else other
if isinstance(othersig, numbers.Number): # When other is just a scalar
@@ -1200,7 +1246,9 @@ def find_events(
sil_min_dur: float = 0.1,
sil_pad: list = [0.001, 0.1],
):
- """Locate meaningful 'events' in the signal and create event list. Onset detection.
+ """
+ Locate meaningful 'events' in the signal and create event list.
+ Onset detection.
Parameters
----------
@@ -1214,13 +1262,15 @@ def find_events(
minimum duration to be counted as silent (Default value = 0.1)
sil_pad : list
this allows you to add a small duration before and after the actual
- found event locations to the event ranges. If it is a list, you can set the padding (Default value = [0.001)
+ found event locations to the event ranges.
+ If it is a list, you can set the padding (Default value = [0.001)
0.1] :
Returns
-------
_ : Asig
- This method returns self. But the list of events can be accessed through self._['events']
+ This method returns self. But the list of events
+ can be accessed through self._['events']
"""
if self.channels > 1:
msg = """warning: works only with single channel.
@@ -1240,7 +1290,7 @@ def find_events(
sil_pad_samples = (int(sil_pad * self.sr),) * 2
event_list = []
for i in range(0, self.samples, step_samples):
- rms = self[i: i + step_samples].rms()
+ rms = self[i : i + step_samples].rms()
if sil_flag:
if rms > sil_thr_amp: # event found
sil_flag = False
@@ -1256,9 +1306,14 @@ def find_events(
if sil_count > sil_min_steps: # event ended
# The below line is new.
if event_end - event_begin >= evt_min_steps:
- event_list.append([event_begin - sil_pad_samples[0],
- event_end - step_samples * sil_min_steps + sil_pad_samples[1], ]
- )
+ event_list.append(
+ [
+ event_begin - sil_pad_samples[0],
+ event_end
+ - step_samples * sil_min_steps
+ + sil_pad_samples[1],
+ ]
+ )
sil_flag = True
self._["events"] = np.array(event_list)
return self
@@ -1302,8 +1357,7 @@ def plot_events(self):
plt.axvline(x=event[0])
plt.axvline(x=event[1], color="r")
except KeyError:
- raise ValueError(
- "No events found, use find_events() before plotting.")
+ raise ValueError("No events found, use find_events() before plotting.")
def fade_in(self, dur: float = 0.1, curve: float = 1):
"""Fade in the signal at the beginning
@@ -1324,7 +1378,8 @@ def fade_in(self, dur: float = 0.1, curve: float = 1):
if nsamp > self.samples:
nsamp = self.samples
warn("warning: Asig too short for fade_in - adapting fade_in time")
- # TODO simplify this if we decide to make mono signal with dimension 1 instead of None.
+ # TODO simplify this if we decide to make mono signal
+ # with dimension 1 instead of None.
if self.channels == 1:
ramp = np.linspace(0, 1, nsamp, dtype="float32") ** curve
return Asig(
@@ -1335,8 +1390,7 @@ def fade_in(self, dur: float = 0.1, curve: float = 1):
)
else:
ramp = np.meshgrid(
- np.linspace(0, 1, nsamp, dtype="float32"), np.zeros(
- self.channels)
+ np.linspace(0, 1, nsamp, dtype="float32"), np.zeros(self.channels)
)[0].T
return Asig(
np.vstack((self.sig[:nsamp] * ramp, self.sig[nsamp:])),
@@ -1364,7 +1418,8 @@ def fade_out(self, dur: float = 0.1, curve: float = 1):
if nsamp > self.samples:
nsamp = self.samples
warn("Asig too short for fade_out - adapting fade_out time")
- # TODO simplify this if we decide to make mono signal with dimension 1 instead of None.
+ # TODO simplify this if we decide to make mono signal
+ # with dimension 1 instead of None.
if self.channels == 1:
ramp = np.linspace(1, 0, nsamp, dtype="float32") ** curve
return Asig(
@@ -1375,8 +1430,7 @@ def fade_out(self, dur: float = 0.1, curve: float = 1):
)
else:
ramp = np.meshgrid(
- np.linspace(1, 0, nsamp, dtype="float32"), np.zeros(
- self.channels)
+ np.linspace(1, 0, nsamp, dtype="float32"), np.zeros(self.channels)
)[0].T
return Asig(
np.vstack((self.sig[:-nsamp], self.sig[-nsamp:] * ramp)),
@@ -1404,28 +1458,33 @@ def iirfilter(
btype : str
Filter type (Default value = 'bandpass')
ftype : str
- Tthe type of IIR filter. e.g. 'butter', 'cheby1', 'cheby2', 'elip', 'bessel' (Default value = 'butter')
+ Tthe type of IIR filter. e.g. 'butter', 'cheby1', 'cheby2', 'elip', 'bessel'
+ (Default value = 'butter')
order : int
Filter order (Default value = 4)
filter : str
- The scipy.signal method to call when applying the filter coeffs to the signal.
+ The scipy.signal method to call
+ when applying the filter coeffs to the signal.
by default it is set to scipy.signal.lfilter (one-dimensional).
rp : float
- For Chebyshev and elliptic filters, provides the maximum ripple in the passband. (dB) (Default value = None)
+ For Chebyshev and elliptic filters,
+ provides the maximum ripple in the passband. (dB) (Default value = None)
rs : float
- For Chebyshev and elliptic filters, provides the minimum attenuation in the stop band. (dB) (Default value = None)
+ For Chebyshev and elliptic filters,
+ provides the minimum attenuation in the stop band. (dB)
+ (Default value = None)
Returns
-------
_ : Asig
- new Asig with the filter applied. also you can access b, a coefficients by doing self._['b']
+ new Asig with the filter applied.
+ also you can access b, a coefficients by doing self._['b']
and self._['a']
"""
# TODO scipy.signal.__getattribute__ error
Wn = np.array(cutoff_freqs) * 2 / self.sr
- b, a = scipy.signal.iirfilter(
- order, Wn, rp=rp, rs=rs, btype=btype, ftype=ftype)
+ b, a = scipy.signal.iirfilter(order, Wn, rp=rp, rs=rs, btype=btype, ftype=ftype)
y = scipy.signal.__getattribute__(filter)(b, a, self.sig, axis=0)
aout = Asig(y, self.sr, label=self.label + "_iir")
aout._["b"] = b
@@ -1434,7 +1493,9 @@ def iirfilter(
return aout
def plot_freqz(self, worN, **kwargs):
- """Plot the frequency response of a digital filter. Perform scipy.signal.freqz then plot the response.
+ """
+ Plot the frequency response of a digital filter.
+ Perform scipy.signal.freqz then plot the response.
TODO
Parameters
@@ -1475,7 +1536,7 @@ def envelope(self, amps, ts=None, curve=1, kind="linear"):
nsteps = len(amps)
duration = self.samples / self.sr
if nsteps == self.samples:
- sig_new = self.sig * amps ** curve
+ sig_new = self.sig * amps**curve
else:
if not ts:
given_ts = np.linspace(0, duration, nsteps)
@@ -1498,13 +1559,22 @@ def envelope(self, amps, ts=None, curve=1, kind="linear"):
raise AttributeError("Asig.envelope error: ts not sorted")
given_ts = ts
if nsteps != self.samples:
- interp_fn = scipy.interpolate.interp1d(
- given_ts, amps, kind=kind)
- sig_new = (self.sig * interp_fn(np.linspace(0, duration, self.samples)) ** curve)
+ interp_fn = scipy.interpolate.interp1d(given_ts, amps, kind=kind)
+ sig_new = (
+ self.sig
+ * interp_fn(np.linspace(0, duration, self.samples)) ** curve
+ )
return Asig(sig_new, self.sr, label=self.label + "_enveloped", cn=self.cn)
- def adsr(self, att: float = 0, dec: float = 0.1, sus: float = 0.7, rel: float = 0.1,
- curve: int = 1, kind: str = "linear"):
+ def adsr(
+ self,
+ att: float = 0,
+ dec: float = 0.1,
+ sus: float = 0.7,
+ rel: float = 0.1,
+ curve: int = 1,
+ kind: str = "linear",
+ ):
"""Create and applied a ADSR evelope to signal.
Parameters
@@ -1542,7 +1612,8 @@ def window(self, win: str = "triang", **kwargs):
Parameters
----------
win : str
- Type of window check scipy.signal.get_window for avaiable types. (Default value = 'triang')
+ Type of window check scipy.signal.get_window for avaiable types.
+ (Default value = 'triang')
**kwargs :
keyword arguments for scipy.signal.get_window()
@@ -1558,12 +1629,15 @@ def window(self, win: str = "triang", **kwargs):
if isinstance(winstr, tuple):
winstr = win[0]
if self.channels == 1:
- return Asig(self.sig * scipy.signal.get_window(win, self.samples, **kwargs),
- self.sr, label=self.label + "_" + winstr, cn=self.cn)
+ return Asig(
+ self.sig * scipy.signal.get_window(win, self.samples, **kwargs),
+ self.sr,
+ label=self.label + "_" + winstr,
+ cn=self.cn,
+ )
else:
for i in range(self.channels):
- self.sig[:,
- i] *= scipy.signal.get_window(win, self.samples, **kwargs)
+ self.sig[:, i] *= scipy.signal.get_window(win, self.samples, **kwargs)
return Asig(self.sig, self.sr, label=self.label + "_" + winstr, cn=self.cn)
def window_op(self, nperseg=64, stride=32, win=None, fn="rms", pad="mirror"):
@@ -1680,12 +1754,17 @@ def overlap_add(
def to_spec(self):
"""Return Aspec object which is the rfft of the signal."""
import pya.aspec
+
return pya.aspec.Aspec(self)
def to_stft(self, **kwargs):
- """Return Astft object which is the stft of the signal. Keyword arguments are the arguments for
- scipy.signal.stft(). """
+ """
+ Return Astft object which is the stft of the signal.
+ Keyword arguments are the arguments for
+ scipy.signal.stft().
+ """
import pya.astft
+
return pya.astft.Astft(self, **kwargs)
def to_mfcc(
@@ -1700,8 +1779,9 @@ def to_mfcc(
preemph=0.95,
append_energy=True,
):
- """Return Amfcc object. """
+ """Return Amfcc object."""
import pya.amfcc
+
return pya.amfcc.Amfcc(
self,
label=self.label,
@@ -1717,7 +1797,13 @@ def to_mfcc(
cn=self.cn,
)
- def plot_spectrum(self, offset: float = 0, scale: float = 1.0, xlim: Optional[Iterable] = None, **kwargs):
+ def plot_spectrum(
+ self,
+ offset: float = 0,
+ scale: float = 1.0,
+ xlim: Optional[Iterable] = None,
+ **kwargs,
+ ):
"""Plot spectrum of the signal
Parameters
@@ -1783,10 +1869,11 @@ def plot_spectrum(self, offset: float = 0, scale: float = 1.0, xlim: Optional[It
return self
def spectrogram(self, *argv, **kvarg):
- """Perform sicpy.signal.spectrogram and returns: frequencies, array of times, spectrogram
"""
- freqs, times, Sxx = scipy.signal.spectrogram(
- self.sig, self.sr, *argv, **kvarg)
+ Perform sicpy.signal.spectrogram and returns:
+ frequencies, array of times, spectrogram
+ """
+ freqs, times, Sxx = scipy.signal.spectrogram(self.sig, self.sr, *argv, **kvarg)
return freqs, times, Sxx
def get_size(self):
@@ -1794,7 +1881,9 @@ def get_size(self):
return self.sig.shape, self.sig.shape[0] / self.sr
def append(self, asig, amp=1):
- """Apppend an asig with another. Conditions: the appended asig should have the same channels. If
+ """
+ Apppend an asig with another. Conditions: the appended asig
+ should have the same channels. If
appended asig has a different sampling rate, resample it to match the orginal.
Parameters
@@ -1856,7 +1945,8 @@ def add(self, sig, pos=None, amp=1, onset=None):
raise AttributeError("Argument asig has different channels.!")
if sr != self.sr:
raise AttributeError(
- "Dangerous operation, samping rate (sr) not matched. Use resample() first."
+ "Dangerous operation, samping rate (sr) not matched. "
+ "Use resample() first."
)
else:
n = np.shape(sig)[0]
@@ -1883,7 +1973,9 @@ def flatten(self):
cn=None,
)
- def pad(self, width: int = 0, tail: bool = True, constant_values: Union[int, float] = 0):
+ def pad(
+ self, width: int = 0, tail: bool = True, constant_values: Union[int, float] = 0
+ ):
"""Pads the signal
Parameters
@@ -1923,22 +2015,29 @@ def convolve(self, sig, mode: str = "full", method: str = "fft", norm: str = "am
mode : str {'full', 'valid', 'same'}
A string indicating the size of the output:
full
- The output is the full discrete linear convolution of the inputs. (Default)
+ The output is the full discrete linear convolution of the inputs.
+ (Default)
valid
- The output consists only of those elements that do not rely on the zero-padding.
- self.sr or ins must be at least as large as the other in every dimension.
+ The output consists only of those elements
+ that do not rely on the zero-padding.
+ self.sr or ins must be at least as large
+ as the other in every dimension.
same
- The output is the same size as self.sr, centered with respect to the full output.
+ The output is the same size as self.sr,
+ centered with respect to the full output.
method : str {'auto', 'direct', 'fft'}
A string indicating which method to use to calculate the convolution
direct
Compute directly from sums, the definition of convolution
fft (default)
- The Fourier Transform is used to perform the convolution by calling fftconvolve
+ The Fourier Transform is used to perform the convolution
+ by calling fftconvolve
auto
- Automatically chooses direct or Fourier method based on an estimate of which is faster.
+ Automatically chooses direct or Fourier method
+ based on an estimate of which is faster.
norm : str
- If "amp" (default value), the result signal will have the same peak as the original signal.
+ If "amp" (default value), the result signal
+ will have the same peak as the original signal.
Otherwise, no normalization is applied.
Returns
@@ -1948,8 +2047,7 @@ def convolve(self, sig, mode: str = "full", method: str = "fft", norm: str = "am
"""
if isinstance(sig, Asig):
if sig.sr != self.sr:
- _LOGGER.warning(
- "sampling rate not matched, perform resampling...")
+ _LOGGER.warning("sampling rate not matched, perform resampling...")
sig = sig.resample(target_sr=self.sr)
sig_array = sig.sig
sig_size = sig.samples
@@ -1959,34 +2057,33 @@ def convolve(self, sig, mode: str = "full", method: str = "fft", norm: str = "am
sig_size = len(sig)
sig_channels = 1 if sig_array.ndim == 1 else sig_array.shape[1]
else:
- raise TypeError(
- "Illegal type. ir must be an Asig object or an array.")
+ raise TypeError("Illegal type. ir must be an Asig object or an array.")
# Compare size of A B, and pad zeros if needed.
if self.samples > sig_size:
# pad ir
sig_array = padding(sig_array, width=self.samples - sig_size)
else:
+ # TODO somehow, this code is not doing anything?
# pad source
- asig = padding(self.sig, width=sig_size - self.samples)
+ _ = padding(self.sig, width=sig_size - self.samples)
# Now perform convolution
if self.channels == 1:
# If sig is a mono signal:
result = np.array(
- scipy.signal.convolve(
- self.sig, sig_array, mode=mode, method=method)
+ scipy.signal.convolve(self.sig, sig_array, mode=mode, method=method)
)
else:
if sig_channels > 1 and self.channels != sig_channels:
raise ValueError(
- "input signal needs to have the same amount of channels as self.sig."
+ "input signal needs to have the same "
+ "amount of channels as self.sig."
)
# Perform conv on each channel.
for i in range(self.channels):
a = self.sig[:, i]
b = sig_array if sig_channels == 1 else sig_array[:, i]
- r_1ch = np.array(scipy.signal.convolve(
- a, b, mode=mode, method=method))
+ r_1ch = np.array(scipy.signal.convolve(a, b, mode=mode, method=method))
if i == 0:
result = np.zeros((len(r_1ch), self.channels))
result[:, i] = r_1ch
@@ -2014,4 +2111,6 @@ def apply(self, fn):
"""
vecfn = np.vectorize(fn)
sig_out = vecfn(self.sig)
- return Asig(sig_out, sr=self.sr, label=self.label, channels=self.channels, cn=self.cn)
+ return Asig(
+ sig_out, sr=self.sr, label=self.label, channels=self.channels, cn=self.cn
+ )
diff --git a/pya/aspec.py b/pya/aspec.py
index 25849b55..8b65973d 100644
--- a/pya/aspec.py
+++ b/pya/aspec.py
@@ -1,12 +1,12 @@
import logging
-from typing import Union, Optional
+from typing import Optional, Union
import numpy as np
import scipy.interpolate
import pya.asig
-from .helper import basicplot
+from .helper import basicplot
_LOGGER = logging.getLogger(__name__)
_LOGGER.addHandler(logging.NullHandler())
@@ -14,8 +14,14 @@
class Aspec:
"""Audio spectrum class using rfft"""
- def __init__(self, x: Union[pya.asig.Asig, np.ndarray], sr: int = 44100,
- label: Optional[str] = None, cn: Optional[list] = None):
+
+ def __init__(
+ self,
+ x: Union[pya.asig.Asig, np.ndarray],
+ sr: int = 44100,
+ label: Optional[str] = None,
+ cn: Optional[list] = None,
+ ):
"""__init__() method
Parameters
----------
@@ -36,7 +42,8 @@ def __init__(self, x: Union[pya.asig.Asig, np.ndarray], sr: int = 44100,
self.channels = x.channels
self.cn = cn or x.cn
elif isinstance(x, np.ndarray):
- # TODO. This is in the assumption x is spec. which is wrong. We define x to be the audio signals instead.
+ # TODO. This is in the assumption x is spec. which is wrong.
+ # We define x to be the audio signals instead.
self.rfftspec = np.array(x)
self.sr = sr
self.samples = (len(x) - 1) * 2
@@ -57,10 +64,14 @@ def get_duration(self):
def to_sig(self):
"""Convert Aspec into Asig"""
- return pya.asig.Asig(np.fft.irfft(self.rfftspec),
- sr=self.sr, label=self.label + '_2sig', cn=self.cn)
-
- def weight(self, weights: list, freqs=None, curve=1, kind='linear'):
+ return pya.asig.Asig(
+ np.fft.irfft(self.rfftspec),
+ sr=self.sr,
+ label=self.label + "_2sig",
+ cn=self.cn,
+ )
+
+ def weight(self, weights: list, freqs=None, curve=1, kind="linear"):
"""TODO
Parameters
@@ -96,18 +107,16 @@ def weight(self, weights: list, freqs=None, curve=1, kind='linear'):
weights = np.insert(np.array(weights), -1, weights[-1])
given_freqs = freqs
if nfreqs != self.nr_freqs:
- interp_fn = scipy.interpolate.interp1d(given_freqs,
- weights, kind=kind)
+ interp_fn = scipy.interpolate.interp1d(given_freqs, weights, kind=kind)
# ToDo: curve segmentwise!!!
rfft_new = self.rfftspec * interp_fn(self.freqs) ** curve
else:
- rfft_new = self.rfftspec * weights ** curve
- return Aspec(rfft_new, self.sr,
- label=self.label + "_weighted", cn=self.cn)
+ rfft_new = self.rfftspec * weights**curve
+ return Aspec(rfft_new, self.sr, label=self.label + "_weighted", cn=self.cn)
- def plot(self, fn=np.abs, ax=None,
- offset=0, scale=1,
- xlim=None, ylim=None, **kwargs):
+ def plot(
+ self, fn=np.abs, ax=None, offset=0, scale=1, xlim=None, ylim=None, **kwargs
+ ):
"""Plot spectrum
Parameters
@@ -132,14 +141,24 @@ def plot(self, fn=np.abs, ax=None,
_ : Asig
self
"""
- _, ax = basicplot(fn(self.rfftspec), self.freqs, channels=self.channels,
- cn=self.cn, offset=offset, scale=scale,
- ax=ax, typ='plot',
- xlabel='freq (Hz)', ylabel=f'{fn.__name__}(freq)',
- xlim=xlim, ylim=ylim, **kwargs)
+ _, ax = basicplot(
+ fn(self.rfftspec),
+ self.freqs,
+ channels=self.channels,
+ cn=self.cn,
+ offset=offset,
+ scale=scale,
+ ax=ax,
+ typ="plot",
+ xlabel="freq (Hz)",
+ ylabel=f"{fn.__name__}(freq)",
+ xlim=xlim,
+ ylim=ylim,
+ **kwargs,
+ )
return self
def __repr__(self):
return "Aspec('{}'): {} x {} @ {} Hz = {:.3f} s".format(
- self.label, self.channels, self.samples,
- self.sr, self.samples / self.sr)
+ self.label, self.channels, self.samples, self.sr, self.samples / self.sr
+ )
diff --git a/pya/astft.py b/pya/astft.py
index 379d9085..53064733 100644
--- a/pya/astft.py
+++ b/pya/astft.py
@@ -1,13 +1,14 @@
from __future__ import absolute_import
+
import logging
-from typing import Union, Optional
+from typing import Optional, Union
import numpy as np
-from scipy.signal import stft, istft
+from scipy.signal import istft, stft
import pya.asig
-from .helper import basicplot
+from .helper import basicplot
_LOGGER = logging.getLogger(__name__)
_LOGGER.addHandler(logging.NullHandler())
@@ -15,15 +16,26 @@
# TODO, check with multichannel
class Astft:
- """Audio spectrogram (STFT) class, attributes refers to scipy.signal.stft. With an addition
- attribute cn being the list of channel names, and label being the name of the Asig
+ """Audio spectrogram (STFT) class, attributes refers to scipy.signal.stft.
+ With an addition attribute cn being the list of channel names,
+ and label being the name of the Asig
"""
- def __init__(self, x: Union[pya.asig.Asig, np.ndarray], sr: Optional[int] = None, label: str = "STFT",
- window: str = 'hann', nperseg: int = 256, noverlap: Optional[int] = None,
- nfft: Optional[int] = None, detrend: bool = False,
- return_onesided: bool = True, boundary: str = 'zeros',
- padded: bool = True, cn: Optional[list] = None):
+ def __init__(
+ self,
+ x: Union[pya.asig.Asig, np.ndarray],
+ sr: Optional[int] = None,
+ label: str = "STFT",
+ window: str = "hann",
+ nperseg: int = 256,
+ noverlap: Optional[int] = None,
+ nfft: Optional[int] = None,
+ detrend: bool = False,
+ return_onesided: bool = True,
+ boundary: str = "zeros",
+ padded: bool = True,
+ cn: Optional[list] = None,
+ ):
"""__init__() method
Parameters
@@ -45,26 +57,37 @@ def __init__(self, x: Union[pya.asig.Asig, np.ndarray], sr: Optional[int] = None
`None`, the FFT length is `nperseg`. Defaults to `None`.
detrend : str or function or bool
Specifies how to detrend each segment. If detrend is a string,
- it is passed as the type argument to the detrend function. If it is a function,
+ it is passed as the type argument to the detrend function.
+ If it is a function,
it takes a segment and returns a detrended segment. If detrend is False,
no detrending is done. (Default value = False).
return_onesided : bool
- If True, return a one-sided spectrum for real data. If False return a two-sided spectrum.
- Defaults to True, but for complex data, a two-sided spectrum is always returned. (Default value = True)
+ If True, return a one-sided spectrum for real data.
+ If False return a two-sided spectrum.
+ Defaults to True, but for complex data,
+ a two-sided spectrum is always returned. (Default value = True)
boundary : str or None
- Specifies whether the input signal is extended at both ends, and how to generate the new values,
+ Specifies whether the input signal is extended at both ends,
+ and how to generate the new values,
in order to center the first windowed segment on the first input point.
This has the benefit of enabling reconstruction of the first input point
when the employed window function starts at zero.
- Valid options are ['even', 'odd', 'constant', 'zeros', None]. Defaults to ‘zeros’,
- for zero padding extension. I.e. [1, 2, 3, 4] is extended to [0, 1, 2, 3, 4, 0] for nperseg=3. (Default value = 'zeros')
+ Valid options are ['even', 'odd', 'constant', 'zeros', None].
+ Defaults to ‘zeros’,
+ for zero padding extension.
+ I.e. [1, 2, 3, 4] is extended to [0, 1, 2, 3, 4, 0] for nperseg=3.
+ (Default value = 'zeros')
padded : bool
- Specifies whether the input signal is zero-padded at the end to make the signal fit exactly into
- an integer number of window segments, so that all of the signal is included in the output.
- Defaults to True. Padding occurs after boundary extension, if boundary is not None, and padded is True,
+ Specifies whether the input signal is zero-padded at the end
+ to make the signal fit exactly into
+ an integer number of window segments,
+ so that all of the signal is included in the output.
+ Defaults to True. Padding occurs after boundary extension,
+ if boundary is not None, and padded is True,
as is the default. (Default value = True)
cn : list, optional
- Channel names of the Asig, this will be used for the Astft for consistency. (Default value = None)
+ Channel names of the Asig, this will be used for the Astft for consistency.
+ (Default value = None)
"""
self.window = window
self.nperseg = nperseg
@@ -91,22 +114,35 @@ def __init__(self, x: Union[pya.asig.Asig, np.ndarray], sr: Optional[int] = None
# x is a numpy array instead of asig.
self.channels = x.ndim
self.samples = len(x)
- self.label = 'stft'
+ self.label = "stft"
self.cn = []
if sr is None:
- raise AttributeError("sr (sampling rate) is required as an argument if input is a numpy array rather than Asig.")
+ raise AttributeError(
+ "sr (sampling rate) is required as an argument "
+ "if input is a numpy array rather than Asig."
+ )
else:
self.sr = sr
sig = x
else:
- raise TypeError("Unknown data type x, x should be either Asig or numpy.ndarray")
-
- self.freqs, self.times, self.stft = \
- stft(sig, fs=self.sr, window=window, nperseg=nperseg,
- noverlap=noverlap, nfft=nfft, detrend=detrend,
- return_onesided=return_onesided, boundary=boundary,
- padded=padded, axis=0)
+ raise TypeError(
+ "Unknown data type x, x should be either Asig or numpy.ndarray"
+ )
+
+ self.freqs, self.times, self.stft = stft(
+ sig,
+ fs=self.sr,
+ window=window,
+ nperseg=nperseg,
+ noverlap=noverlap,
+ nfft=nfft,
+ detrend=detrend,
+ return_onesided=return_onesided,
+ boundary=boundary,
+ padded=padded,
+ axis=0,
+ )
if cn:
if len(cn) == self.channels:
@@ -131,26 +167,43 @@ def to_sig(self, **kwargs):
_ : Asig
Asig
"""
- for k in ['sr', 'window', 'nperseg', 'noverlap',
- 'nfft', 'input_onesided', 'boundary']:
+ for k in [
+ "sr",
+ "window",
+ "nperseg",
+ "noverlap",
+ "nfft",
+ "input_onesided",
+ "boundary",
+ ]:
if k in kwargs.keys():
kwargs[k] = self.__getattribute__(k)
- if 'sr' in kwargs.keys():
- kwargs['fs'] = kwargs['sr']
- del kwargs['sr']
+ if "sr" in kwargs.keys():
+ kwargs["fs"] = kwargs["sr"]
+ del kwargs["sr"]
if self.channels == 1:
# _ since 1st return value 'times' unused
_, sig = istft(self.stft, **kwargs)
- return pya.asig.Asig(sig, sr=self.sr,
- label=self.label + '_2sig', cn=self.cn)
+ return pya.asig.Asig(
+ sig, sr=self.sr, label=self.label + "_2sig", cn=self.cn
+ )
else:
_, sig = istft(self.stft, **kwargs)
- return pya.asig.Asig(np.transpose(sig),
- sr=self.sr, label=self.label + '_2sig', cn=self.cn)
-
- def plot(self, fn=lambda x: x, ax=None,
- offset=0, scale=1., xlim=None, ylim=None,
- show_bar=True, **kwargs):
+ return pya.asig.Asig(
+ np.transpose(sig), sr=self.sr, label=self.label + "_2sig", cn=self.cn
+ )
+
+ def plot(
+ self,
+ fn=lambda x: x,
+ ax=None,
+ offset=0,
+ scale=1.0,
+ xlim=None,
+ ylim=None,
+ show_bar=True,
+ **kwargs,
+ ):
"""Plot spectrogram
Parameters
@@ -173,15 +226,30 @@ def plot(self, fn=lambda x: x, ax=None,
_ : Asig
self
"""
- self.im, ax = basicplot(fn(np.abs(self.stft)), (self.times, self.freqs),
- channels=self.channels,
- cn=self.cn, offset=offset, scale=scale,
- ax=ax, typ='spectrogram', show_bar=show_bar,
- xlabel='time', xlim=xlim, ylim=ylim, **kwargs)
- ax.set_ylabel('freq')
+ self.im, ax = basicplot(
+ fn(np.abs(self.stft)),
+ (self.times, self.freqs),
+ channels=self.channels,
+ cn=self.cn,
+ offset=offset,
+ scale=scale,
+ ax=ax,
+ typ="spectrogram",
+ show_bar=show_bar,
+ xlabel="time",
+ xlim=xlim,
+ ylim=ylim,
+ **kwargs,
+ )
+ ax.set_ylabel("freq")
return self
def __repr__(self):
return "Astft('{}'): {} x {} @ {} Hz = {:.3f} s cn={}".format(
- self.label, self.channels, self.samples,
- self.sr, self.samples / self.sr, self.cn)
+ self.label,
+ self.channels,
+ self.samples,
+ self.sr,
+ self.samples / self.sr,
+ self.cn,
+ )
diff --git a/pya/backend/Dummy.py b/pya/backend/Dummy.py
index 96c35d0d..9a4ccf19 100644
--- a/pya/backend/Dummy.py
+++ b/pya/backend/Dummy.py
@@ -1,17 +1,22 @@
-from .base import BackendBase, StreamBase
-import numpy as np
-from threading import Thread
import time
+from threading import Thread
+import numpy as np
-class DummyBackend(BackendBase):
+from pya.backend.base import BackendBase, StreamBase
- dtype = 'float32'
+__all__ = ["DummyBackend", "DummyStream"]
+
+
+class DummyBackend(BackendBase):
+ dtype = "float32"
range = 1
bs = 256
def __init__(self):
- self.dummy_devices = [dict(maxInputChannels=10, maxOutputChannels=10, index=0, name="DummyDevice")]
+ self.dummy_devices = [
+ dict(maxInputChannels=10, maxOutputChannels=10, index=0, name="DummyDevice")
+ ]
def get_device_count(self):
return len(self.dummy_devices)
@@ -25,13 +30,28 @@ def get_default_input_device_info(self):
def get_default_output_device_info(self):
return self.dummy_devices[0]
- def open(self, *args, input_flag, output_flag, rate, frames_per_buffer, channels, stream_callback=None, **kwargs):
- checker = 'maxInputChannels' if input_flag else 'maxOutputChannels'
+ def open(
+ self,
+ *args,
+ input_flag,
+ output_flag,
+ rate,
+ frames_per_buffer,
+ channels,
+ stream_callback=None,
+ **kwargs,
+ ):
+ checker = "maxInputChannels" if input_flag else "maxOutputChannels"
if channels > self.dummy_devices[0][checker]:
raise OSError("[Errno -9998] Invalid number of channels")
- stream = DummyStream(input_flag=input_flag, output_flag=output_flag,
- rate=rate, frames_per_buffer=frames_per_buffer, channels=channels,
- stream_callback=stream_callback)
+ stream = DummyStream(
+ input_flag=input_flag,
+ output_flag=output_flag,
+ rate=rate,
+ frames_per_buffer=frames_per_buffer,
+ channels=channels,
+ stream_callback=stream_callback,
+ )
stream.start_stream()
return stream
@@ -43,8 +63,15 @@ def terminate(self):
class DummyStream(StreamBase):
-
- def __init__(self, input_flag, output_flag, frames_per_buffer, rate, channels, stream_callback):
+ def __init__(
+ self,
+ input_flag,
+ output_flag,
+ frames_per_buffer,
+ rate,
+ channels,
+ stream_callback,
+ ):
self.input_flag = input_flag
self.output_flag = output_flag
self.rate = rate
@@ -58,8 +85,9 @@ def __init__(self, input_flag, output_flag, frames_per_buffer, rate, channels, s
def stop_stream(self):
self._is_active = False
- while (self.in_thread and self.in_thread.is_alive()) or \
- (self.out_thread and self.out_thread.is_alive()):
+ while (self.in_thread and self.in_thread.is_alive()) or (
+ self.out_thread and self.out_thread.is_alive()
+ ):
time.sleep(0.1)
def close(self):
@@ -67,7 +95,9 @@ def close(self):
def _generate_data(self):
while self._is_active:
- sig = np.zeros(self.frames_per_buffer * self.channels, dtype=DummyBackend.dtype)
+ sig = np.zeros(
+ self.frames_per_buffer * self.channels, dtype=DummyBackend.dtype
+ )
self.stream_callback(sig, frame_count=None, time_info=None, flag=None)
time.sleep(0.05)
diff --git a/pya/backend/Jupyter.py b/pya/backend/Jupyter.py
index 710871ae..e9e9159d 100644
--- a/pya/backend/Jupyter.py
+++ b/pya/backend/Jupyter.py
@@ -1,28 +1,35 @@
-from .base import BackendBase, StreamBase
-
import asyncio
import threading
-from functools import partial
-from IPython.display import Javascript, HTML, display
+
+from IPython.display import HTML, Javascript, display
+
+from pya.backend.base import BackendBase, StreamBase
try:
import websockets
except ImportError:
websockets = None
+__all__ = ["JupyterBackend", "JupyterStream"]
-class JupyterBackend(BackendBase):
- dtype = 'float32'
+class JupyterBackend(BackendBase):
+ dtype = "float32"
range = 1
bs = 4096 # streaming introduces lack which has to be covered by the buffer
def __init__(self, port=8765, proxy_suffix=None):
if not websockets:
- raise Exception("JupyterBackend requires 'websockets' but it could not be imported. "
- "Did you miss installing optional 'remote' requirements?")
-
- self.dummy_devices = [dict(maxInputChannels=0, maxOutputChannels=2, index=0, name="JupyterBackend")]
+ raise Exception(
+ "JupyterBackend requires 'websockets' but it could not be imported. "
+ "Did you miss installing optional 'remote' requirements?"
+ )
+
+ self.dummy_devices = [
+ dict(
+ maxInputChannels=0, maxOutputChannels=2, index=0, name="JupyterBackend"
+ )
+ ]
self.port = port
self.proxy_suffix = proxy_suffix
if self.proxy_suffix is not None:
@@ -41,11 +48,20 @@ def get_default_output_device_info(self):
return self.dummy_devices[0]
def open(self, *args, channels, rate, stream_callback=None, **kwargs):
- display(HTML("You are using the experimental Jupyter backend. "
- "Note that this backend is not feature complete and does not support recording so far. "
- "User experience may vary depending on the network latency.
"))
- stream = JupyterStream(channels=channels, rate=rate, stream_callback=stream_callback, port=self.port,
- proxy_suffix=self.proxy_suffix)
+ display(
+ HTML(
+ 'You are using the experimental Jupyter backend. ' # noqa E501
+ "Note that this backend is not feature complete and does not support recording so far. " # noqa E501
+ "User experience may vary depending on the network latency.
"
+ )
+ )
+ stream = JupyterStream(
+ channels=channels,
+ rate=rate,
+ stream_callback=stream_callback,
+ port=self.port,
+ proxy_suffix=self.proxy_suffix,
+ )
stream.start_stream()
return stream
@@ -57,7 +73,6 @@ def terminate(self):
class JupyterStream(StreamBase):
-
def __init__(self, channels, rate, stream_callback, port, proxy_suffix):
self.rate = rate
self.channels = channels
@@ -69,7 +84,7 @@ async def bridge(websocket):
async for _ in websocket:
buffer = self.stream_callback(None, None, None, None)
# print(buffer)
- await websocket.send(buffer.reshape(-1, 1, order='F').tobytes())
+ await websocket.send(buffer.reshape(-1, 1, order="F").tobytes())
async def ws_runner():
async with websockets.serve(bridge, "0.0.0.0", 8765):
@@ -85,9 +100,10 @@ def loop_thread(loop):
self.loop = asyncio.new_event_loop()
self.thread = threading.Thread(target=loop_thread, args=(self.loop,))
- # self.thread.daemon = True # allow program to shutdown even if the thread is alive
+ # allow program to shutdown even if the thread is alive
+ # self.thread.daemon = True
- url_suffix = f':{port}' if proxy_suffix is None else proxy_suffix
+ url_suffix = f":{port}" if proxy_suffix is None else proxy_suffix
self.client = Javascript(
f"""
@@ -191,7 +207,8 @@ def loop_thread(loop):
}
console.log("PyaJSClient: Websocket client loaded.")
- """)
+ """ # noqa E501
+ )
@staticmethod
def set_buffer_threshold(buffer_limit):
diff --git a/pya/backend/PyAudio.py b/pya/backend/PyAudio.py
index df9b83ff..47547eaa 100644
--- a/pya/backend/PyAudio.py
+++ b/pya/backend/PyAudio.py
@@ -1,11 +1,15 @@
-from .base import BackendBase
+import time
import pyaudio
-import time
+from pya.backend.base import BackendBase
-class PyAudioBackend(BackendBase):
+__all__ = [
+ "PyAudioBackend",
+]
+
+class PyAudioBackend(BackendBase):
_boot_delay = 0.5 # a short delay to prevent PyAudio racing conditions
bs = 512
@@ -13,13 +17,15 @@ def __init__(self, format=pyaudio.paFloat32):
self.pa = pyaudio.PyAudio()
self.format = format
if format == pyaudio.paInt16:
- self.dtype = 'int16'
+ self.dtype = "int16"
self.range = 32767
elif format == pyaudio.paFloat32:
- self.dtype = 'float32' # for pyaudio.paFloat32
+ self.dtype = "float32" # for pyaudio.paFloat32
self.range = 1.0
else:
- raise AttributeError(f"Aserver: currently unsupported pyaudio format {self.format}")
+ raise AttributeError(
+ f"Aserver: currently unsupported pyaudio format {self.format}"
+ )
def get_device_count(self):
return self.pa.get_device_count()
@@ -33,16 +39,34 @@ def get_default_input_device_info(self):
def get_default_output_device_info(self):
return self.pa.get_default_output_device_info()
- def open(self, rate, channels, input_flag, output_flag, frames_per_buffer,
- input_device_index=None, output_device_index=None, start=True,
- input_host_api_specific_stream_info=None, output_host_api_specific_stream_info=None,
- stream_callback=None):
- stream = self.pa.open(rate=rate, channels=channels, format=self.format, input=input_flag, output=output_flag,
- input_device_index=input_device_index, output_device_index=output_device_index,
- frames_per_buffer=frames_per_buffer, start=start,
- input_host_api_specific_stream_info=input_host_api_specific_stream_info,
- output_host_api_specific_stream_info=output_host_api_specific_stream_info,
- stream_callback=stream_callback)
+ def open(
+ self,
+ rate,
+ channels,
+ input_flag,
+ output_flag,
+ frames_per_buffer,
+ input_device_index=None,
+ output_device_index=None,
+ start=True,
+ input_host_api_specific_stream_info=None,
+ output_host_api_specific_stream_info=None,
+ stream_callback=None,
+ ):
+ stream = self.pa.open(
+ rate=rate,
+ channels=channels,
+ format=self.format,
+ input=input_flag,
+ output=output_flag,
+ input_device_index=input_device_index,
+ output_device_index=output_device_index,
+ frames_per_buffer=frames_per_buffer,
+ start=start,
+ input_host_api_specific_stream_info=input_host_api_specific_stream_info,
+ output_host_api_specific_stream_info=output_host_api_specific_stream_info,
+ stream_callback=stream_callback,
+ )
time.sleep(self._boot_delay) # give stream some time to be opened completely
return stream
diff --git a/pya/backend/__init__.py b/pya/backend/__init__.py
index b2ec81ce..60c44580 100644
--- a/pya/backend/__init__.py
+++ b/pya/backend/__init__.py
@@ -1,21 +1,25 @@
-from .Dummy import DummyBackend
import logging
+from pya.backend.Dummy import DummyBackend
+from pya.helper.backend import determine_backend
+
_LOGGER = logging.getLogger(__name__)
_LOGGER.addHandler(logging.NullHandler())
+__all__ = ["DummyBackend", "determine_backend"]
try:
- from .Jupyter import JupyterBackend
+ from pya.backend.Jupyter import JupyterBackend as JupyterBackend
+
+ __all__.append("JupyterBackend")
except ImportError: # pragma: no cover
_LOGGER.warning("Jupyter backend not found.")
pass
try:
- from .PyAudio import PyAudioBackend
+ from pya.backend.PyAudio import PyAudioBackend as PyAudioBackend
+
+ __all__.append("PyAudioBackend")
except ImportError: # pragma: no cover
_LOGGER.warning("PyAudio backend not found.")
pass
-
-
-from ..helper.backend import determine_backend
diff --git a/pya/backend/base.py b/pya/backend/base.py
index c773b8a8..e38cb4ea 100644
--- a/pya/backend/base.py
+++ b/pya/backend/base.py
@@ -1,8 +1,7 @@
-from abc import abstractmethod, ABC
+from abc import ABC, abstractmethod
class BackendBase(ABC):
-
@abstractmethod
def get_device_count(self):
raise NotImplementedError
@@ -33,7 +32,6 @@ def process_buffer(self, *args, **kwargs):
class StreamBase(ABC):
-
@abstractmethod
def is_active(self):
raise NotImplementedError
diff --git a/pya/helper/__init__.py b/pya/helper/__init__.py
index 1c37b5cf..2873b81a 100644
--- a/pya/helper/__init__.py
+++ b/pya/helper/__init__.py
@@ -1,5 +1,6 @@
# from .helpers import audio_from_file, buf_to_float, spectrum, audio_from_file
# from .helpers import normalize, device_info, find_device
# from .helpers import padding, shift_bit_length
-from .helpers import *
-from .visualization import basicplot, gridplot
+from .helpers import * # noqa: F403
+from .visualization import basicplot as basicplot
+from .visualization import gridplot as gridplot
diff --git a/pya/helper/backend.py b/pya/helper/backend.py
index 47162f24..3f7424b7 100644
--- a/pya/helper/backend.py
+++ b/pya/helper/backend.py
@@ -1,26 +1,35 @@
-from typing import Optional, TYPE_CHECKING
+from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
from pya.backend.base import BackendBase
- from pya.backend.PyAudio import PyAudioBackend
from pya.backend.Jupyter import JupyterBackend
+ from pya.backend.PyAudio import PyAudioBackend
+
+
+__all__ = [
+ "get_server_info",
+ "try_pyaudio_backend",
+ "try_jupyter_backend",
+ "determine_backend",
+]
def get_server_info():
- import re
import json
- import requests
+ import re
+
import ipykernel
import notebook.notebookapp
+ import requests
+
kernel_id = re.search(
- "kernel-(.*).json",
- ipykernel.connect.get_connection_file()
+ "kernel-(.*).json", ipykernel.connect.get_connection_file()
).group(1)
servers = notebook.notebookapp.list_running_servers()
for s in servers:
response = requests.get(
requests.compat.urljoin(s["url"], "api/sessions"),
- params={"token": s.get("token", "")}
+ params={"token": s.get("token", "")},
)
for n in json.loads(response.text):
if n["kernel"]["id"] == kernel_id:
@@ -31,6 +40,7 @@ def get_server_info():
def try_pyaudio_backend(**kwargs) -> Optional["PyAudioBackend"]:
try:
from pya.backend.PyAudio import PyAudioBackend
+
return PyAudioBackend(**kwargs)
except ImportError:
return None
@@ -38,11 +48,18 @@ def try_pyaudio_backend(**kwargs) -> Optional["PyAudioBackend"]:
def try_jupyter_backend(port, **kwargs) -> Optional["JupyterBackend"]:
import os
+
from pya.backend.Jupyter import JupyterBackend
+
server_info = get_server_info()
- if server_info is None or (server_info['hostname'] in ['localhost', '127.0.0.1'] and not force_webaudio):
+ if server_info is None or (
+ server_info["hostname"] in ["localhost", "127.0.0.1"]
+ # TODO commented out the `force_webaudio` condition below,
+ # because it was undefined
+ # `and not force_webaudio`
+ ):
return None # use default local backend
- if os.environ.get('BINDER_SERVICE_HOST'):
+ if os.environ.get("BINDER_SERVICE_HOST"):
return JupyterBackend(port=port, proxy_suffix=f"/proxy/{port}", **kwargs)
else:
return JupyterBackend(port=port, **kwargs)
diff --git a/pya/helper/codec.py b/pya/helper/codec.py
index b6ea021c..40d4f502 100644
--- a/pya/helper/codec.py
+++ b/pya/helper/codec.py
@@ -1,19 +1,39 @@
"""
-Audio codec module supporting high-quality audio file reading with consistent float32 output.
-Supports WAV, AIFF, FLAC (via SoundFile) and MP3 (via FFmpeg) while maintaining maximum precision.
+Audio codec module supporting high-quality audio file reading
+with consistent float32 output.
+Supports WAV, AIFF, FLAC (via SoundFile) and MP3 (via FFmpeg)
+while maintaining maximum precision.
"""
-import sys
-import subprocess
-import re
-import time
import os
-import threading
-from warnings import warn
import queue
+import re
+import subprocess
+import sys
+import threading
+import time
-import soundfile as sf
import numpy as np
+import soundfile as sf
+
+__all__ = [
+ "DecodeError",
+ "NoFileError",
+ "NoBackendError",
+ "UnsupportedError",
+ "BitWidthError",
+ "FFmpegError",
+ "FFmpegNotInstalledError",
+ "FFmpegReadTimeoutError",
+ "CommunicationError",
+ "BaseAudioFile",
+ "SoundFileAudioFile",
+ "QueueReaderThread",
+ "popen_multiple",
+ "ffmpeg_available",
+ "FFmpegAudioFile",
+ "audio_read",
+]
COMMANDS = ("ffmpeg", "avconv")
@@ -296,7 +316,7 @@ def __init__(self, filename, block_size=4096):
@property
def raw_str_info(self) -> str:
- """Example info: 'duration: 00:00:00.81, start: 0.025057, bitrate: 84 kb/sstream #0:0: audio: mp3 (mp3float), 44100 hz, mono, fltp, 82 kb/s'"""
+ """Example info: 'duration: 00:00:00.81, start: 0.025057, bitrate: 84 kb/sstream #0:0: audio: mp3 (mp3float), 44100 hz, mono, fltp, 82 kb/s'""" # noqa: E501
return self._raw_str_info
def _get_info(self):
@@ -329,7 +349,7 @@ def _parse_info(self, str_info):
"""Given relevant data from the ffmpeg output, set audio
parameter fields on this object.
Example: 'duration: 00:00:00.81, start: 0.025057, bitrate: 84 kb/sstream #0:0: audio: mp3 (mp3float), 44100 hz, mono, fltp, 82 kb/s'
- """
+ """ # noqa: E501
# Sample rate.
match = re.search(r"(\d+) hz", str_info)
if match:
@@ -356,7 +376,12 @@ def _parse_info(self, str_info):
match = re.search(r"duration: (\d+):(\d+):(\d+).(\d)", str_info)
if match:
durparts = list(map(int, match.groups()))
- self._duration = (durparts[0] * 60 * 60 + durparts[1] * 60 + durparts[2] + float(durparts[3]) / 10)
+ self._duration = (
+ durparts[0] * 60 * 60
+ + durparts[1] * 60
+ + durparts[2]
+ + float(durparts[3]) / 10
+ )
else:
self._duration = 0
diff --git a/pya/helper/helpers.py b/pya/helper/helpers.py
index f0b3c0d3..e9df1779 100644
--- a/pya/helper/helpers.py
+++ b/pya/helper/helpers.py
@@ -1,18 +1,36 @@
# Collection of small helper functions
-import numpy as np
-from scipy.fftpack import fft
-from .codec import audio_read
-import logging
import decimal
+import logging
import math
+import numpy as np
+from scipy.fftpack import fft
+
+from .codec import audio_read
-class _error(Exception):
- pass
+__all__ = [
+ "spectrum",
+ "normalize",
+ "audio_from_file",
+ "buf_to_float",
+ "_try_initializing_pyaudio",
+ "device_info",
+ "find_device",
+ "padding",
+ "is_pow2",
+ "next_pow2",
+ "round_half_up",
+ "rolling_window",
+ "signal_to_frame",
+ "magspec",
+ "powspec",
+]
def spectrum(sig, samples, channels, sr):
- """Return spectrum of a given signal. This method return spectrum matrix if input signal is multi-channels.
+ """
+ Return spectrum of a given signal.
+ This method return spectrum matrix if input signal is multi-channels.
Parameters
----------
@@ -52,9 +70,9 @@ def normalize(d):
def audio_from_file(path: str):
- '''Load an audio buffer using audio_read.
+ """Load an audio buffer using audio_read.
Returns a tuple of (samples, samplerate) where samples is a numpy float32 array.
- '''
+ """
y = []
with audio_read(path) as input_file:
sr_native = input_file.samplerate
@@ -91,9 +109,9 @@ def buf_to_float(x, n_bytes=2, dtype=np.float32):
The input data buffer cast to floating point
"""
# Invert the scale of the data
- scale = 1. / float(1 << ((8 * n_bytes) - 1))
+ scale = 1.0 / float(1 << ((8 * n_bytes) - 1))
# Construct the format string
- fmt = '= min_input and dev['maxOutputChannels'] >= min_output:
+ if (
+ dev["maxInputChannels"] >= min_input
+ and dev["maxOutputChannels"] >= min_output
+ ):
res.append(dev)
return res
def padding(x, width, tail=True, constant_values=0):
- """Pad signal with certain width, support 1-3D tensors.
+ """Pad signal with certain width, support 1-3D tensors.
Use it to add silence to a signal
TODO: CHECK pad array
@@ -148,7 +167,7 @@ def padding(x, width, tail=True, constant_values=0):
x : np.ndarray
A numpy array
width : int
- The amount of padding.
+ The amount of padding.
tail : bool
If true pad to the tail, else pad to the start.
constant_values : int or float or None
@@ -161,13 +180,19 @@ def padding(x, width, tail=True, constant_values=0):
"""
pad = (0, width) if tail else (width, 0)
if x.ndim == 1:
- return np.pad(x, (pad), mode='constant', constant_values=constant_values)
+ return np.pad(x, (pad), mode="constant", constant_values=constant_values)
elif x.ndim == 2:
- return np.pad(x, (pad, (0, 0)), mode='constant', constant_values=constant_values)
+ return np.pad(
+ x, (pad, (0, 0)), mode="constant", constant_values=constant_values
+ )
elif x.ndim == 3:
- return np.pad(x, ((0, 0), pad, (0, 0)), mode='constant', constant_values=constant_values)
+ return np.pad(
+ x, ((0, 0), pad, (0, 0)), mode="constant", constant_values=constant_values
+ )
else:
- raise AttributeError("only support ndim 1 or 2, 3. For higher please just use np.pad ")
+ raise AttributeError(
+ "only support ndim 1 or 2, 3. For higher please just use np.pad "
+ )
def is_pow2(val):
@@ -176,7 +201,7 @@ def is_pow2(val):
def next_pow2(x):
- """Find the closest pow of 2 that is great or equal or x,
+ """Find the closest pow of 2 that is great or equal or x,
based on shift_bit_length
Parameters
@@ -196,7 +221,11 @@ def next_pow2(x):
def round_half_up(number):
"""Round up if >= .5"""
- return int(decimal.Decimal(number).quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP))
+ return int(
+ decimal.Decimal(number).quantize(
+ decimal.Decimal("1"), rounding=decimal.ROUND_HALF_UP
+ )
+ )
def rolling_window(a, window, step=1):
@@ -215,7 +244,8 @@ def signal_to_frame(sig, n_per_frame, frame_step, window=None, stride_trick=True
n_per_frame : int
Number of samples each frame
frame_step : int
- Number of samples after the start of the previous frame that the next frame should begin.
+ Number of samples after the start of the previous
+ frame that the next frame should begin.
window : numpy.ndarray or None
A window array, e.g,
stride_trick : bool
@@ -243,8 +273,12 @@ def signal_to_frame(sig, n_per_frame, frame_step, window=None, stride_trick=True
win = np.ones(n_per_frame)
frames = rolling_window(padsignal, window=n_per_frame, step=frame_step)
else:
- indices = np.tile(np.arange(0, n_per_frame), (numframes, 1)) + np.tile(
- np.arange(0, numframes * frame_step, frame_step), (n_per_frame, 1)).T
+ indices = (
+ np.tile(np.arange(0, n_per_frame), (numframes, 1))
+ + np.tile(
+ np.arange(0, numframes * frame_step, frame_step), (n_per_frame, 1)
+ ).T
+ )
indices = np.array(indices, dtype=np.int32)
frames = padsignal[indices]
if window is not None:
@@ -273,14 +307,16 @@ def magspec(frames, NFFT):
Each row will be the magnitude spectrum of the corresponding frame.
"""
if np.shape(frames)[1] > NFFT:
- logging.warning(f'frame length {np.shape(frames)[1]} is greater than FFT size {NFFT}, '
- f'frame will be truncated. Increase NFFT to avoid.')
+ logging.warning(
+ f"frame length {np.shape(frames)[1]} is greater than FFT size {NFFT}, "
+ f"frame will be truncated. Increase NFFT to avoid."
+ )
complex_spec = np.fft.rfft(frames, NFFT)
return np.abs(complex_spec)
def powspec(frames, NFFT):
- """Compute the power spectrum of each frame in frames,
+ """Compute the power spectrum of each frame in frames,
first comeputer the magnitude spectrum
Parameters
@@ -293,7 +329,7 @@ def powspec(frames, NFFT):
Returns
-------
_ : numpy array
- Power spectrum of the framed signal.
+ Power spectrum of the framed signal.
Each row has the size of NFFT / 2 + 1 due to rfft.
"""
return 1.0 / NFFT * np.square(magspec(frames, NFFT))
diff --git a/pya/helper/visualization.py b/pya/helper/visualization.py
index 92f1c5eb..028c860e 100644
--- a/pya/helper/visualization.py
+++ b/pya/helper/visualization.py
@@ -1,19 +1,35 @@
from __future__ import absolute_import
-import matplotlib.pyplot as plt
+
import math
-import numpy as np
+
import matplotlib.gridspec as grd
+import matplotlib.pyplot as plt
+import numpy as np
from mpl_toolkits.axes_grid1 import make_axes_locatable
+__all__ = ["basicplot", "gridplot"]
-def basicplot(data: np.ndarray, ticks, channels, offset=0, scale=1,
- cn=None, ax=None, typ='plot', cmap='inferno',
- xlim=None, ylim=None, xlabel='', ylabel='',
- show_bar=False,
- **kwargs):
+
+def basicplot(
+ data: np.ndarray,
+ ticks,
+ channels,
+ offset=0,
+ scale=1,
+ cn=None,
+ ax=None,
+ typ="plot",
+ cmap="inferno",
+ xlim=None,
+ ylim=None,
+ xlabel="",
+ ylabel="",
+ show_bar=False,
+ **kwargs,
+):
"""Basic version of the plot for pya, this can be directly used
by Asig. Aspec/Astft/Amfcc will have different extra setting
- and type.
+ and type.
Parameters
----------
@@ -34,27 +50,32 @@ def basicplot(data: np.ndarray, ticks, channels, offset=0, scale=1,
# offset is the spacing between channel,
# scale is can shrink the signal just for visualization purpose.
# Plot everything on top of each other.
- if typ == 'plot':
+ if typ == "plot":
p = ax.plot(ticks, data, **kwargs)
# return p, ax
- elif typ == 'spectrogram':
+ elif typ == "spectrogram":
# ticks is (times, freqs)
- p = ax.pcolormesh(ticks[0], ticks[1], data,
- cmap=plt.get_cmap(cmap), **kwargs)
- elif typ == 'mfcc':
+ p = ax.pcolormesh(
+ ticks[0], ticks[1], data, cmap=plt.get_cmap(cmap), **kwargs
+ )
+ elif typ == "mfcc":
p = ax.pcolormesh(data, cmap=plt.get_cmap(cmap), **kwargs)
else:
- if typ == 'plot':
+ if typ == "plot":
for idx, val in enumerate(data.T):
p = ax.plot(ticks, idx * offset + val * scale, **kwargs)
ax.set_xlabel(xlabel)
if cn:
ax.text(0, (idx + 0.1) * offset, cn[idx])
- elif typ == 'spectrogram':
+ elif typ == "spectrogram":
for idx in range(data.shape[1]):
- p = ax.pcolormesh(ticks[0], idx * offset + scale * ticks[1],
- data[:, idx, :], cmap=plt.get_cmap(cmap),
- **kwargs)
+ p = ax.pcolormesh(
+ ticks[0],
+ idx * offset + scale * ticks[1],
+ data[:, idx, :],
+ cmap=plt.get_cmap(cmap),
+ **kwargs,
+ )
if cn:
ax.text(0, (idx + 0.1) * offset, cn[idx])
ax.set_yticklabels([])
@@ -66,7 +87,7 @@ def basicplot(data: np.ndarray, ticks, channels, offset=0, scale=1,
# Colorbar
if show_bar:
divider = make_axes_locatable(ax)
- cax = divider.append_axes('right', size="2%", pad=0.03)
+ cax = divider.append_axes("right", size="2%", pad=0.03)
_ = plt.colorbar(p, cax=cax) # Add
return p, ax
@@ -83,7 +104,7 @@ def gridplot(pya_objects, colwrap=1, cbar_ratio=0.04, figsize=None):
# plot all 4 different pya objects in 1 column,
amfcc and astft use pcolormesh so colorbar will
# be displayed as well
- gridplot([asig, amfcc, aspec, astft], colwrap=2,
+ gridplot([asig, amfcc, aspec, astft], colwrap=2,
cbar_ratio=0.08, figsize=[10, 10]);
Parameters
@@ -105,7 +126,8 @@ def gridplot(pya_objects, colwrap=1, cbar_ratio=0.04, figsize=None):
fig : plt.figure()
The plt.figure() object
"""
- from .. import Asig, Amfcc, Astft, Aspec
+ from .. import Amfcc, Asig, Aspec, Astft
+
nplots = len(pya_objects)
if colwrap > nplots:
@@ -125,8 +147,7 @@ def gridplot(pya_objects, colwrap=1, cbar_ratio=0.04, figsize=None):
wratio.append(odd_weight) if i % 2 else wratio.append(even_weight)
fig = plt.figure(figsize=figsize, constrained_layout=True)
- grid = grd.GridSpec(nrow, ncol,
- figure=fig, width_ratios=wratio, wspace=0.01)
+ grid = grd.GridSpec(nrow, ncol, figure=fig, width_ratios=wratio, wspace=0.01)
total_idx = ncol * nrow
for i in range(total_idx):
@@ -135,9 +156,13 @@ def gridplot(pya_objects, colwrap=1, cbar_ratio=0.04, figsize=None):
if idx < nplots:
ax = plt.subplot(grid[i])
# Title is object type + label
- title = pya_objects[idx].__repr__().split('(')[0] + ': ' + pya_objects[idx].label
+ title = (
+ pya_objects[idx].__repr__().split("(")[0]
+ + ": "
+ + pya_objects[idx].label
+ )
# Truncate if str too long
- title = (title[:30] + "..." if len(title) > 30 else title)
+ title = title[:30] + "..." if len(title) > 30 else title
ax.set_title(title)
if isinstance(pya_objects[idx], Asig):
pya_objects[idx].plot(ax=ax)
diff --git a/pya/ugen.py b/pya/ugen.py
index e7e18b1e..06772bac 100644
--- a/pya/ugen.py
+++ b/pya/ugen.py
@@ -1,14 +1,19 @@
+from typing import Optional, Union
+
import numpy as np
from scipy import signal
-from typing import Optional, Union
from . import Asig
from .helper import normalize
def get_num_of_rows(dur: Optional[float], n_rows: Optional[int], sr: int):
- """Return total number of samples. If dur is set, return dur*sr, if num_samples is set, return num_samples,
- if both set, raise an AttributeError. Only use one of the two.
+ """
+ Return total number of samples.
+ If dur is set, return dur*sr,
+ if num_samples is set, return num_samples,
+ if both set, raise an AttributeError.
+ Only use one of the two.
"""
if dur and n_rows is None:
return int(dur * sr)
@@ -17,7 +22,9 @@ def get_num_of_rows(dur: Optional[float], n_rows: Optional[int], sr: int):
elif n_rows and dur is None:
return int(n_rows)
else:
- raise AttributeError("Only use either dur or n_rows to specify the number of rows of the signal.")
+ raise AttributeError(
+ "Only use either dur or n_rows to specify the number of rows of the signal."
+ )
class Ugen(Asig):
@@ -38,12 +45,21 @@ class Ugen(Asig):
>>> # Make a white noise, another option is 'pink', at 44100Hz for 1second.
>>> noi = Ugen().noise(type='white')
"""
+
def __init__(self):
pass
- def sine(self, freq: Union[int, float] = 440, amp: Union[int, float] = 1.0,
- dur: Optional[float] = None, n_rows: Optional[int] = None,
- sr: int = 44100, channels: int = 1, cn: Optional[list] = None, label: str = "sine"):
+ def sine(
+ self,
+ freq: Union[int, float] = 440,
+ amp: Union[int, float] = 1.0,
+ dur: Optional[float] = None,
+ n_rows: Optional[int] = None,
+ sr: int = 44100,
+ channels: int = 1,
+ cn: Optional[list] = None,
+ label: str = "sine",
+ ):
"""Generate Sine signal Asig object.
Parameters
@@ -53,15 +69,18 @@ def sine(self, freq: Union[int, float] = 440, amp: Union[int, float] = 1.0,
amp : int, float
signal amplitude (Default value = 1.0)
dur : float
- duration in second. dur and n_rows only use one of the two. (Default value = 1.0)
+ duration in second. dur and n_rows only use one of the two.
+ (Default value = 1.0)
n_rows : int
- number of rows (samples). dur and n_rows only use one of the two(Default value = None)
+ number of rows (samples). dur and n_rows only use one of the two
+ (Default value = None)
sr : int
sampling rate (Default value = 44100)
channels : int
number of channels (Default value = 1)
cn : list of string
- channel names as a list. The size needs to match the number of channels (Default value = None)
+ channel names as a list. The size needs to match the number of channels
+ (Default value = None)
label : string
identifier of the object (Default value = "sine")
@@ -70,15 +89,25 @@ def sine(self, freq: Union[int, float] = 440, amp: Union[int, float] = 1.0,
Asig
"""
length = get_num_of_rows(dur, n_rows, sr)
- sig = amp * np.sin(2 * np.pi * freq * np.linspace(0, length / sr, length, endpoint=False))
+ sig = amp * np.sin(
+ 2 * np.pi * freq * np.linspace(0, length / sr, length, endpoint=False)
+ )
if channels > 1:
sig = np.repeat(sig, channels)
sig = sig.reshape((length, channels))
return Asig(sig, sr=sr, label=label, channels=channels, cn=cn)
- def cos(self, freq: Union[int, float] = 440, amp: Union[int, float] = 1.0,
- dur: Optional[float] = None, n_rows: Optional[int] = None,
- sr: int = 44100, channels: int = 1, cn: Optional[list] = None, label: str = "cosine"):
+ def cos(
+ self,
+ freq: Union[int, float] = 440,
+ amp: Union[int, float] = 1.0,
+ dur: Optional[float] = None,
+ n_rows: Optional[int] = None,
+ sr: int = 44100,
+ channels: int = 1,
+ cn: Optional[list] = None,
+ label: str = "cosine",
+ ):
"""Generate Cosine signal Asig object.
Parameters
@@ -88,15 +117,18 @@ def cos(self, freq: Union[int, float] = 440, amp: Union[int, float] = 1.0,
amp : int, float
signal amplitude (Default value = 1.0)
dur : int, float
- duration in second. dur and num_rows only use one of the two. (Default value = 1.0)
+ duration in second. dur and num_rows only use one of the two.
+ (Default value = 1.0)
n_rows : int
- number of rows (samples). dur and num_rows only use one of the two(Default value = None)
+ number of rows (samples). dur and num_rows only use one of the two
+ (Default value = None)
sr : int
sampling rate (Default value = 44100)
channels : int
number of channels (Default value = 1)
cn : list of string
- channel names as a list. The size needs to match the number of channels (Default value = None)
+ channel names as a list. The size needs to match the number of channels
+ (Default value = None)
label : string
identifier of the object (Default value = "cosine")
@@ -105,15 +137,27 @@ def cos(self, freq: Union[int, float] = 440, amp: Union[int, float] = 1.0,
Asig
"""
length = get_num_of_rows(dur, n_rows, sr)
- sig = amp * np.cos(2 * np.pi * freq * np.linspace(0, length / sr, length, endpoint=False))
+ sig = amp * np.cos(
+ 2 * np.pi * freq * np.linspace(0, length / sr, length, endpoint=False)
+ )
if channels > 1:
sig = np.repeat(sig, channels)
sig = sig.reshape((length, channels))
return Asig(sig, sr=sr, label=label, channels=channels, cn=cn)
- def square(self, freq=440, amp=1.0, dur=None, n_rows=None,
- duty=0.5, sr=44100, sample_shift=0.5,
- channels=1, cn=None, label="square"):
+ def square(
+ self,
+ freq=440,
+ amp=1.0,
+ dur=None,
+ n_rows=None,
+ duty=0.5,
+ sr=44100,
+ sample_shift=0.5,
+ channels=1,
+ cn=None,
+ label="square",
+ ):
"""Generate square wave signal Asig object.
Parameters
@@ -123,9 +167,11 @@ def square(self, freq=440, amp=1.0, dur=None, n_rows=None,
amp : int, float
signal amplitude (Default value = 1.0)
dur : int, float
- duration in second. dur and num_rows only use one of the two. (Default value = 1.0)
+ duration in second. dur and num_rows only use one of the two.
+ (Default value = 1.0)
num_rows : int
- number of row (samples). dur and num_rows only use one of the two(Default value = None)
+ number of row (samples). dur and num_rows only use one of the two
+ (Default value = None)
duty : float
duty cycle (Default value = 0.4)
sr : int
@@ -133,7 +179,8 @@ def square(self, freq=440, amp=1.0, dur=None, n_rows=None,
channels : int
number of channels (Default value = 1)
cn : list of string
- channel names as a list. The size needs to match the number of channels (Default value = None)
+ channel names as a list. The size needs to match the number of channels
+ (Default value = None)
label : string
identifier of the object (Default value = "square")
@@ -143,15 +190,32 @@ def square(self, freq=440, amp=1.0, dur=None, n_rows=None,
"""
length = get_num_of_rows(dur, n_rows, sr)
sig = amp * signal.square(
- 2 * np.pi * freq * ((sample_shift / length) + np.linspace(0, length / sr, length, endpoint=False)),
- duty=duty)
+ 2
+ * np.pi
+ * freq
+ * (
+ (sample_shift / length)
+ + np.linspace(0, length / sr, length, endpoint=False)
+ ),
+ duty=duty,
+ )
if channels > 1:
sig = np.repeat(sig, channels)
sig = sig.reshape((length, channels))
return Asig(sig, sr=sr, label=label, channels=channels, cn=cn)
- def sawtooth(self, freq=440, amp=1.0, dur=None, n_rows=None,
- width=1., sr=44100, channels=1, cn=None, label="sawtooth"):
+ def sawtooth(
+ self,
+ freq=440,
+ amp=1.0,
+ dur=None,
+ n_rows=None,
+ width=1.0,
+ sr=44100,
+ channels=1,
+ cn=None,
+ label="sawtooth",
+ ):
"""Generate sawtooth wave signal Asig object.
Parameters
@@ -161,9 +225,11 @@ def sawtooth(self, freq=440, amp=1.0, dur=None, n_rows=None,
amp : int, float
signal amplitude (Default value = 1.0)
dur : int, float
- duration in second. dur and num_rows only use one of the two. (Default value = 1.0)
+ duration in second. dur and num_rows only use one of the two.
+ (Default value = 1.0)
num_rows : int
- number of rows (samples). dur and num_rows only use one of the two(Default value = None)
+ number of rows (samples). dur and num_rows only use one of the two.
+ (Default value = None)
width : float
tooth width (Default value = 1.0)
sr : int
@@ -171,7 +237,8 @@ def sawtooth(self, freq=440, amp=1.0, dur=None, n_rows=None,
channels : int
number of channels (Default value = 1)
cn : list of string
- channel names as a list. The size needs to match the number of channels (Default value = None)
+ channel names as a list. The size needs to match the number of channels
+ (Default value = None)
label : string
identifier of the object (Default value = "sawtooth")
@@ -180,33 +247,48 @@ def sawtooth(self, freq=440, amp=1.0, dur=None, n_rows=None,
Asig
"""
length = get_num_of_rows(dur, n_rows, sr)
- sig = amp * signal.sawtooth(2 * np.pi * freq * np.linspace(0, length / sr, length, endpoint=False),
- width=width)
+ sig = amp * signal.sawtooth(
+ 2 * np.pi * freq * np.linspace(0, length / sr, length, endpoint=False),
+ width=width,
+ )
if channels > 1:
sig = np.repeat(sig, channels)
sig = sig.reshape((length, channels))
return Asig(sig, sr=sr, label=label, channels=channels, cn=cn)
- def noise(self, type="white", amp=1.0, dur=None, n_rows=None,
- sr=44100, channels=1, cn=None, label="noise"):
+ def noise(
+ self,
+ type="white",
+ amp=1.0,
+ dur=None,
+ n_rows=None,
+ sr=44100,
+ channels=1,
+ cn=None,
+ label="noise",
+ ):
"""Generate noise signal Asig object.
Parameters
----------
type : string
- type of noise, currently available: 'white' and 'pink' (Default value = 'white')
+ type of noise, currently available: 'white' and 'pink'
+ (Default value = 'white')
amp : int, float
signal amplitude (Default value = 1.0)
dur : int, float
- duration in second. dur and num_rows only use one of the two. (Default value = 1.0)
+ duration in second. dur and num_rows only use one of the two.
+ (Default value = 1.0)
num_rows : int
- number of rows (samples). dur and num_rows only use one of the two(Default value = None)
+ number of rows (samples). dur and num_rows only use one of the two
+ (Default value = None)
sr : int
sampling rate (Default value = 44100)
channels : int
number of channels (Default value = 1)
cn : list of string
- channel names as a list. The size needs to match the number of channels (Default value = None)
+ channel names as a list. The size needs to match the number of channels
+ (Default value = None)
label : string
identifier of the object (Default value = "square")
@@ -217,7 +299,7 @@ def noise(self, type="white", amp=1.0, dur=None, n_rows=None,
length = get_num_of_rows(dur, n_rows, sr)
# Question is that will be that be too slow.]
if type == "white" or type == "white_noise":
- sig = (np.random.rand(length) - 0.5) * 2. * amp
+ sig = (np.random.rand(length) - 0.5) * 2.0 * amp
elif type == "pink" or type == "pink_noise":
# Based on Paul Kellet's method
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..1b42236e
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,91 @@
+[project]
+name = "pya"
+version = "0.5.2"
+description = 'Python audio coding classes - for dsp, sound synthesis and and sonification'
+authors = [
+ { name = "Thomas Hermann", email = "thermann@techfak.uni-bielefeld.de"},
+ { name = "Jiajun Yang", email = ""},
+ { name = "Alexander Neumann ...", email = ""},
+
+ { name = "Dennis Reinsch", email = "dreinsch@techfak.uni-bielefeld.de"},
+ { name = "Jannis Müller", email = ""},
+]
+maintainers = [
+ {name = "Fabian Hommel", email = "fhommel@techfak.uni-bielefeld.de"}
+]
+readme = "README.md"
+keywords=["sonification", "sound synthesis"]
+requires-python = ">=3.11"
+license = "MIT"
+license-files = ["LICEN[CS]E*"]
+classifiers = [
+ "Programming Language :: Python :: 3",
+ "Development Status :: 4 - Beta",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ "Topic :: Multimedia :: Sound/Audio",
+ "Topic :: Multimedia :: Sound/Audio :: Analysis",
+ "Topic :: Multimedia :: Sound/Audio :: Sound Synthesis"
+]
+dependencies = [
+ "pyamapping",
+ "scipy>=1.7.3",
+ "matplotlib>=3.5.3",
+ "soundfile>=0.13.0"
+]
+
+[project.urls]
+github = "https://github.com/interactive-sonification/pya"
+
+
+
+[project.optional-dependencies]
+example-notebooks = ["notebook"]
+pyaudio = [ "pyaudio>=0.2.12" ]
+remote = [ "notebook", "websocket", "ipywidgets" ]
+
+[tool.uv]
+dev-dependencies = [
+ "tox",
+ "pytest",
+ "pytest-cov",
+ "pre-commit",
+ "sphinx==7.2.6",
+ "sphinx-rtd-theme==2.0.0",
+ "myst-parser",
+ "pydocstyle",
+]
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build.targets.wheel]
+packages = ["pya"]
+
+[tool.ruff]
+line-length = 88
+exclude = ["examples/", "dev/"]
+
+[tool.ruff.lint]
+select = ["E", "F", "I", "T10"] # E/F = flake8, I = isort
+ignore = ["E702"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["pya"]
+
+[tool.ruff.lint.pydocstyle]
+convention = "numpy"
+
+[tool.pytest.ini_options]
+addopts = "--cov=pya --cov-report=lcov --cov-report=term-missing"
+testpaths = ["tests"]
+
+[tool.coverage.run]
+source = ["pya"]
+
+[tool.coverage.report]
+exclude_lines = [
+ "pragma: no cover",
+ "raise NotImplementedError",
+]
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 3f59cf94..00000000
--- a/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-pyamapping
-scipy>=1.7.3
-matplotlib>=3.5.3
-soundfile>=0.13.0
diff --git a/requirements_doc.txt b/requirements_doc.txt
deleted file mode 100644
index 5cfe83a1..00000000
--- a/requirements_doc.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Sphinx==7.2.6
-sphinx-autoapi==3.0.0
-sphinx-rtd-theme==2.0.0
-sphinx-mdinclude
diff --git a/requirements_pyaudio.txt b/requirements_pyaudio.txt
deleted file mode 100644
index 3d851244..00000000
--- a/requirements_pyaudio.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-pyaudio>=0.2.12; python_version >= '3.10'
-pyaudio>=0.2.11; python_version < '3.10'
diff --git a/requirements_remote.txt b/requirements_remote.txt
deleted file mode 100644
index 3e82c3ce..00000000
--- a/requirements_remote.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-notebook
-websockets
-ipywidgets
diff --git a/requirements_test.txt b/requirements_test.txt
deleted file mode 100644
index 3cdea4b6..00000000
--- a/requirements_test.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-pytest
-pytest-cov
-pycodestyle
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index df4ba59e..00000000
--- a/setup.cfg
+++ /dev/null
@@ -1,7 +0,0 @@
-[metadata]
-description-file = README.md
-
-[check-manifest]
-ignore =
- .travis.yml
- pya/notes.md
diff --git a/setup.py b/setup.py
deleted file mode 100644
index c6559caa..00000000
--- a/setup.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from setuptools import setup, find_packages
-import os
-import codecs
-from os.path import join
-
-project_root = os.path.dirname(os.path.abspath(__file__))
-
-version = {}
-REQUIRED_EXTRAS = {}
-with open(join(project_root, 'pya/version.py')) as read_file:
- exec(read_file.read(), version)
-
-with open(join(project_root, 'requirements.txt')) as read_file:
- REQUIRED = read_file.read().splitlines()
-
-with open(join(project_root, 'requirements_remote.txt')) as read_file:
- REQUIRED_EXTRAS['remote'] = read_file.read().splitlines()
-
-with open(join(project_root, 'requirements_pyaudio.txt')) as read_file:
- REQUIRED_EXTRAS['pyaudio'] = read_file.read().splitlines()
-
-with open(join(project_root, 'requirements_test.txt')) as read_file:
- REQUIRED_TEST = read_file.read().splitlines()
-
-with codecs.open(join(project_root, 'README.md'), 'r', 'utf-8') as f:
- long_description = ''.join(f.readlines())
-
-setup(
- name='pya',
- version=version['__version__'],
- description='Python audio coding classes - for dsp and sonification',
- long_description=long_description,
- long_description_content_type="text/markdown",
- license='MIT',
- packages=find_packages(exclude=["tests"]),
- install_requires=REQUIRED,
- extras_require=REQUIRED_EXTRAS,
- tests_require=REQUIRED_TEST,
- author='Thomas Hermann',
- author_email='thermann@techfak.uni-bielefeld.de',
- keywords=['sonification, sound synthesis'],
- url='https://github.com/interactive-sonification/pya',
- classifiers=[
- "Programming Language :: Python :: 3",
- "Development Status :: 4 - Beta",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- "Topic :: Multimedia :: Sound/Audio",
- "Topic :: Multimedia :: Sound/Audio :: Analysis",
- "Topic :: Multimedia :: Sound/Audio :: Sound Synthesis"
- ],
-)
diff --git a/tests/test_amfcc.py b/tests/test_amfcc.py
index 06606a46..424f6691 100644
--- a/tests/test_amfcc.py
+++ b/tests/test_amfcc.py
@@ -1,8 +1,10 @@
# from pya import Amfcc
-from pya import Asig, Ugen, Amfcc
+import warnings
from unittest import TestCase
+
import numpy as np
-import warnings
+
+from pya import Amfcc, Ugen
class TestAmfcc(TestCase):
@@ -16,7 +18,7 @@ def tearDown(self):
def test_construct(self):
# If x is asig, it will ignore sr but use x.sr instead.
amfcc = Amfcc(self.test_asig, sr=45687)
- self.assertEqual(amfcc.sr, 8000, msg='sr does not match.')
+ self.assertEqual(amfcc.sr, 8000, msg="sr does not match.")
# if x is ndarray and sr is not given
with self.assertRaises(AttributeError):
@@ -37,11 +39,11 @@ def test_get_attributes(self):
def test_hopsize_greater_than_npframe(self):
with warnings.catch_warnings(record=True):
- amfcc = Amfcc(self.test_asig, hopsize=100, n_per_frame=50)
+ _ = Amfcc(self.test_asig, hopsize=100, n_per_frame=50)
def test_nfft_not_pow2(self):
with warnings.catch_warnings(record=True):
- amfcc = Amfcc(self.test_asig, nfft=23)
+ _ = Amfcc(self.test_asig, nfft=23)
def test_nowindowing(self):
amfcc = Amfcc(self.test_asig, window=False)
@@ -49,8 +51,12 @@ def test_nowindowing(self):
self.assertTrue(np.array_equal(result, amfcc.window))
def test_preemphasis(self):
- self.assertTrue(np.array_equal(np.array([0., 1., 1.5, 2., 2.5]),
- Amfcc.preemphasis(np.arange(5), coeff=0.5)))
+ self.assertTrue(
+ np.array_equal(
+ np.array([0.0, 1.0, 1.5, 2.0, 2.5]),
+ Amfcc.preemphasis(np.arange(5), coeff=0.5),
+ )
+ )
def test_melfb(self):
fb = Amfcc.mel_filterbanks(8000) # Using default
@@ -68,4 +74,4 @@ def test_plot_with_multichannel(self):
asig = Ugen().sine(channels=2)
amfcc = asig.to_mfcc()
with warnings.catch_warnings(record=True):
- amfcc.plot()
\ No newline at end of file
+ amfcc.plot()
diff --git a/tests/test_arecorder.py b/tests/test_arecorder.py
index 27718dbc..9298f81b 100644
--- a/tests/test_arecorder.py
+++ b/tests/test_arecorder.py
@@ -1,52 +1,56 @@
# Test arecorder class.
-import time
-from pya import Arecorder, Aserver, find_device
+import importlib.util
from unittest import TestCase, mock
-import pytest
+
import numpy as np
+import pytest
-try:
- import pyaudio
- has_pyaudio = True
-except ImportError:
- has_pyaudio = False
-
-
-FAKE_INPUT = {'index': 0,
- 'structVersion': 2,
- 'name': 'Mock Input',
- 'hostApi': 0,
- 'maxInputChannels': 1,
- 'maxOutputChannels': 0,
- 'defaultLowInputLatency': 0.04852607709750567,
- 'defaultLowOutputLatency': 0.01,
- 'defaultHighInputLatency': 0.05868480725623583,
- 'defaultHighOutputLatency': 0.1,
- 'defaultSampleRate': 44100.0}
-
-FAKE_OUTPUT = {'index': 1,
- 'structVersion': 2,
- 'name': 'Mock Output',
- 'hostApi': 0,
- 'maxInputChannels': 2,
- 'maxOutputChannels': 0,
- 'defaultLowInputLatency': 0.01,
- 'defaultLowOutputLatency': 0.02,
- 'defaultHighInputLatency': 0.03,
- 'defaultHighOutputLatency': 0.04,
- 'defaultSampleRate': 44100.0}
-
-FAKE_AUDIO_INTERFACE = {'index': 2,
- 'structVersion': 2,
- 'name': 'Mock Audio Interface',
- 'hostApi': 0,
- 'maxInputChannels': 14,
- 'maxOutputChannels': 14,
- 'defaultLowInputLatency': 0.01,
- 'defaultLowOutputLatency': 0.02,
- 'defaultHighInputLatency': 0.03,
- 'defaultHighOutputLatency': 0.04,
- 'defaultSampleRate': 48000.0}
+from pya import Arecorder
+
+has_pyaudio = importlib.util.find_spec("pyaudio") is not None
+
+
+FAKE_INPUT = {
+ "index": 0,
+ "structVersion": 2,
+ "name": "Mock Input",
+ "hostApi": 0,
+ "maxInputChannels": 1,
+ "maxOutputChannels": 0,
+ "defaultLowInputLatency": 0.04852607709750567,
+ "defaultLowOutputLatency": 0.01,
+ "defaultHighInputLatency": 0.05868480725623583,
+ "defaultHighOutputLatency": 0.1,
+ "defaultSampleRate": 44100.0,
+}
+
+FAKE_OUTPUT = {
+ "index": 1,
+ "structVersion": 2,
+ "name": "Mock Output",
+ "hostApi": 0,
+ "maxInputChannels": 2,
+ "maxOutputChannels": 0,
+ "defaultLowInputLatency": 0.01,
+ "defaultLowOutputLatency": 0.02,
+ "defaultHighInputLatency": 0.03,
+ "defaultHighOutputLatency": 0.04,
+ "defaultSampleRate": 44100.0,
+}
+
+FAKE_AUDIO_INTERFACE = {
+ "index": 2,
+ "structVersion": 2,
+ "name": "Mock Audio Interface",
+ "hostApi": 0,
+ "maxInputChannels": 14,
+ "maxOutputChannels": 14,
+ "defaultLowInputLatency": 0.01,
+ "defaultLowOutputLatency": 0.02,
+ "defaultHighInputLatency": 0.03,
+ "defaultHighOutputLatency": 0.04,
+ "defaultSampleRate": 48000.0,
+}
class MockRecorder(mock.MagicMock):
@@ -74,14 +78,17 @@ def get_default_output_device_info(self):
class MockBackend:
"""Mock audio backend for testing"""
+
def __init__(self, **kwargs):
- self.dummy_devices = [{
- 'index': 0,
- 'maxInputChannels': 2,
- 'maxOutputChannels': 2,
- 'defaultSampleRate': 44100
- }]
- self.dtype = 'float32'
+ self.dummy_devices = [
+ {
+ "index": 0,
+ "maxInputChannels": 2,
+ "maxOutputChannels": 2,
+ "defaultSampleRate": 44100,
+ }
+ ]
+ self.dtype = "float32"
self.range = 1.0
self.bs = 256
@@ -106,6 +113,7 @@ def terminate(self):
class MockStream:
"""Mock audio stream for testing"""
+
def __init__(self):
self._active = True
@@ -148,15 +156,14 @@ class TestArecorder(TestArecorderBase):
class TestMockArecorder(TestCase):
-
@pytest.mark.skipif(not has_pyaudio, reason="requires pyaudio to be installed")
def test_mock_arecorder(self):
mock_recorder = MockRecorder()
- with mock.patch('pyaudio.PyAudio', return_value=mock_recorder):
+ with mock.patch("pyaudio.PyAudio", return_value=mock_recorder):
ar = Arecorder()
self.assertEqual(
- "Mock Input",
- ar.backend.get_default_input_device_info()['name'])
+ "Mock Input", ar.backend.get_default_input_device_info()["name"]
+ )
ar.boot()
self.assertTrue(mock_recorder.open.called)
ar.record()
@@ -168,6 +175,6 @@ def test_mock_arecorder(self):
# ar.stop() # Dont know how to mock the stop.
# TODO How to mock a result.
- # Mock multiple input devices.
+ # Mock multiple input devices.
ar.set_device(2, reboot=True) # Set to multiple device
self.assertEqual(ar.max_in_chn, 14)
diff --git a/tests/test_aserver.py b/tests/test_aserver.py
index 1c6a9f60..bd5f24a9 100644
--- a/tests/test_aserver.py
+++ b/tests/test_aserver.py
@@ -1,16 +1,19 @@
+import time
from unittest import TestCase
-from pya import *
+
import numpy as np
-import time
+from pya.aserver import Aserver
+from pya.asig import Asig
+from pya.backend.Dummy import DummyBackend
-class TestAserver(TestCase):
+class TestAserver(TestCase):
def setUp(self) -> None:
self.backend = DummyBackend()
self.sig = np.sin(2 * np.pi * 440 * np.linspace(0, 1, 44100))
self.asine = Asig(self.sig, sr=44100, label="test_sine")
- self.max_channels = self.backend.dummy_devices[0]['maxOutputChannels']
+ self.max_channels = self.backend.dummy_devices[0]["maxOutputChannels"]
def test_default_server(self):
Aserver.startup_default_server(backend=self.backend, bs=512, channels=4)
@@ -38,7 +41,10 @@ def test_custom_channels(self):
self.assertFalse(s.is_active)
def test_invalid_channels(self):
- """Raise an exception if booting with channels greater than max channels of the device. Dummy has 10"""
+ """
+ Raise an exception if booting with channels greater than max channels of the
+ device. Dummy has 10
+ """
ch = 100
s = Aserver(device=0, channels=ch, backend=self.backend)
with self.assertRaises(OSError):
@@ -114,9 +120,10 @@ def test_quit_not_booted(self):
def test_incompatible_backend(self):
s = Aserver(backend=self.backend)
- sig = np.sin(2 * np.pi * 440 * np.linspace(0, 1, 44100) * np.iinfo(np.int16).max).astype(np.int16)
+ sig = np.sin(
+ 2 * np.pi * 440 * np.linspace(0, 1, 44100) * np.iinfo(np.int16).max
+ ).astype(np.int16)
asine = Asig(sig, sr=44100)
s.boot()
asine.play(server=s)
s.quit()
-
diff --git a/tests/test_asig.py b/tests/test_asig.py
index 2f5643ea..100aedb4 100644
--- a/tests/test_asig.py
+++ b/tests/test_asig.py
@@ -1,22 +1,23 @@
+from math import inf
from unittest import TestCase, mock
-from unittest.mock import patch
-from pya import Asig
+
import numpy as np
-from math import inf
-import os
+
+from pya import Asig
class TestAsig(TestCase):
"""Unit Tests for Asig"""
+
def setUp(self):
self.sig = np.sin(2 * np.pi * 100 * np.linspace(0, 1, 44100))
self.asine = Asig(self.sig, sr=44100, label="test_sine")
- self.asineWithName = Asig(self.sig, sr=44100, label="test_sine", cn=['sine'])
+ self.asineWithName = Asig(self.sig, sr=44100, label="test_sine", cn=["sine"])
self.sig2ch = np.repeat(self.sig, 2).reshape((44100, 2))
- self.astereo = Asig(self.sig2ch, sr=44100, label="sterep", cn=['l', 'r'])
+ self.astereo = Asig(self.sig2ch, sr=44100, label="sterep", cn=["l", "r"])
self.sig16ch = np.repeat(self.sig, 16).reshape((44100, 16))
self.asine16ch = Asig(self.sig16ch, sr=44100, label="test_sine_16ch")
- self.asigconst = Asig(1.0, sr=100, label="constant signal", cn=['0']) + 0.5
+ self.asigconst = Asig(1.0, sr=100, label="constant signal", cn=["0"]) + 0.5
def tearDown(self):
pass
@@ -30,17 +31,22 @@ def test_asig_constructor(self):
def test_asig_plot(self):
self.asine.plot()
- self.astereo.plot(offset=1., scale=0.5)
+ self.astereo.plot(offset=1.0, scale=0.5)
def test_duration(self):
- self.assertEqual(self.asine.get_duration(), 1.)
- get_time = self.asine.get_times()
- self.assertTrue(np.array_equal(np.linspace(0,
- (self.asine.samples - 1) / self.asine.sr,
- self.asine.samples), self.asine.get_times()))
+ self.assertEqual(self.asine.get_duration(), 1.0)
+ _ = self.asine.get_times()
+ self.assertTrue(
+ np.array_equal(
+ np.linspace(
+ 0, (self.asine.samples - 1) / self.asine.sr, self.asine.samples
+ ),
+ self.asine.get_times(),
+ )
+ )
def test_dur_property(self):
- self.assertEqual(self.asine.dur, 1.)
+ self.assertEqual(self.asine.dur, 1.0)
def test_fader(self):
result = self.asine.fade_in(dur=0.2)
@@ -59,19 +65,19 @@ def test_channels(self):
self.assertEqual(4, as1.channels)
def test_cn(self):
- self.assertEqual(self.astereo.cn, ['l', 'r'])
- self.astereo.cn = ['left', 'right'] # Test changing the cn
- self.assertEqual(self.astereo.cn, ['left', 'right'])
+ self.assertEqual(self.astereo.cn, ["l", "r"])
+ self.astereo.cn = ["left", "right"] # Test changing the cn
+ self.assertEqual(self.astereo.cn, ["left", "right"])
with self.assertRaises(ValueError):
- self.astereo.cn = ['left', 'right', 'middle']
+ self.astereo.cn = ["left", "right", "middle"]
with self.assertRaises(TypeError): # If list is not string only, TypeError
self.astereo.cn = ["b", 10]
with self.assertRaises(TypeError): # If list is not string only, TypeError
- asig = Asig(1000, channels=3, cn=3)
+ _ = Asig(1000, channels=3, cn=3)
- self.assertEqual(self.astereo.cn, ['left', 'right'])
+ self.assertEqual(self.astereo.cn, ["left", "right"])
def test_remove_DC(self):
result = self.asigconst.remove_DC()
@@ -79,11 +85,11 @@ def test_remove_DC(self):
result = Asig(100, channels=2) + 0.25
result[:, 1] = 0.5
self.assertEqual([0.25, 0.5], list(np.max(result.sig, 0)))
- self.assertEqual([0., 0.], list(result.remove_DC().sig.max(axis=0)))
+ self.assertEqual([0.0, 0.0], list(result.remove_DC().sig.max(axis=0)))
def test_norm(self):
result = self.astereo.norm()
- result = self.astereo.norm(norm=1., dcflag=True)
+ result = self.astereo.norm(norm=1.0, dcflag=True)
self.assertEqual(1, np.max(result.sig))
result = self.astereo.norm(norm=2, dcflag=True)
self.assertEqual(2, np.max(result.sig))
@@ -96,24 +102,28 @@ def test_gain(self):
current_max_amplitude = np.max(self.astereo.sig)
result = self.astereo.gain() # by default amp=1. nothing change.
- self.assertEqual(current_max_amplitude, np.max(result.sig), "gain() should not change anything")
+ self.assertEqual(
+ current_max_amplitude,
+ np.max(result.sig),
+ "gain() should not change anything",
+ )
- result = self.astereo.gain(amp=2.)
+ result = self.astereo.gain(amp=2.0)
self.assertEqual(2, np.max(result.sig))
- result = self.astereo.gain(db=3.)
+ result = self.astereo.gain(db=3.0)
with self.assertRaises(AttributeError):
- _ = self.astereo.gain(amp=1, db=3.)
+ _ = self.astereo.gain(amp=1, db=3.0)
- result = self.astereo.gain(amp=0.)
+ result = self.astereo.gain(amp=0.0)
self.assertEqual(0, np.max(result.sig), "amp 0 should result in 0")
def test_rms(self):
- result = self.asine16ch.rms()
+ _ = self.asine16ch.rms()
def test_plot(self):
self.asine.plot(xlim=(0, 1), ylim=(-1, 1))
- self.asine.plot(fn='db')
+ self.asine.plot(fn="db")
self.astereo.plot(offset=1)
self.asine16ch.plot(offset=1, scale=0.5)
@@ -126,8 +136,10 @@ def test_add(self):
self.assertIsInstance(adding, Asig)
self.assertTrue(np.array_equal([10, 12, 14, 16], adding.sig))
- # asig + ndarray actually we don't encourage that. Because of sampling rate may differ
- # also because ndarray + asig works. so it is strongly against adding asig with ndarray.
+ # asig + ndarray actually we don't encourage that.
+ # Because of sampling rate may differ
+ # also because ndarray + asig works.
+ # so it is strongly against adding asig with ndarray.
# just maker another asig and add both together.
adding = a + b0
self.assertIsInstance(adding, Asig)
@@ -162,14 +174,16 @@ def test_mul(self):
# Testing multiplication beween asig and asig, or asig with a scalar.
a = Asig(np.arange(4), sr=2)
a2 = Asig(np.arange(8), sr=2)
- a4ch = Asig(np.ones((4, 4)), sr=2)
- a4ch2 = Asig(np.ones((8, 4)), sr=2)
+ _ = Asig(np.ones((4, 4)), sr=2)
+ _ = Asig(np.ones((8, 4)), sr=2)
self.assertTrue(np.array_equal([0, 4, 8, 12], (a * 4).sig))
self.assertTrue(np.array_equal([0, 4, 8, 12], (4 * a).sig))
self.assertTrue(np.array_equal([0, 1, 4, 9], (a * a).sig))
self.assertTrue(np.array_equal([0, 1, 4, 9], (a.bound * a2).sig))
- self.assertTrue(np.array_equal([0., 1., 4., 9., 4., 5., 6., 7.], (a.x * a2).sig))
+ self.assertTrue(
+ np.array_equal([0.0, 1.0, 4.0, 9.0, 4.0, 5.0, 6.0, 7.0], (a.x * a2).sig)
+ )
def test_subtract(self):
a = Asig(np.arange(4), sr=2)
@@ -182,16 +196,16 @@ def test_subtract(self):
b = Asig(np.ones(6), sr=2)
self.assertTrue(np.array_equal([-1, 0, 1, 2], (a.bound - b).sig))
with self.assertRaises(ValueError):
- adding = a - b
+ _ = a - b
self.assertTrue(np.array_equal([-1, 0, 1, 2, -1, -1], (a.x - b).sig))
def test_division(self):
# Testing multiplication beween asig and asig, or asig with a scalar.
#
a = Asig(np.arange(4), sr=2)
- a2 = Asig(np.arange(8), sr=2)
+ _ = Asig(np.arange(8), sr=2)
a4ch = Asig(np.ones((4, 4)), sr=2)
- a4ch2 = Asig(np.ones((8, 4)), sr=2)
+ _ = Asig(np.ones((8, 4)), sr=2)
self.assertTrue(np.array_equal([0, 0.25, 0.5, 0.75], (a / 4).sig))
self.assertTrue(np.allclose([inf, 4, 2, 1.33333333], (4 / a).sig))
@@ -199,37 +213,75 @@ def test_division(self):
def test_windowing(self):
asig = Asig(np.ones(10), sr=2)
- asig_windowed = asig.window_op(nperseg=2, stride=1,
- win='hann', fn='rms', pad='mirror')
- self.assertTrue(np.allclose([1., 0.70710677, 0.70710677, 0.70710677,
- 0.70710677, 0.70710677, 0.70710677,
- 0.70710677, 0.70710677, 1.],
- asig_windowed.sig))
+ asig_windowed = asig.window_op(
+ nperseg=2, stride=1, win="hann", fn="rms", pad="mirror"
+ )
+ self.assertTrue(
+ np.allclose(
+ [
+ 1.0,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 1.0,
+ ],
+ asig_windowed.sig,
+ )
+ )
asig2ch = Asig(np.ones((10, 2)), sr=2)
- asig2ch.window_op(nperseg=2, stride=1, win='hann', fn='rms', pad='mirror')
- a = [1., 0.70710677, 0.70710677, 0.70710677,
- 0.70710677, 0.70710677, 0.70710677,
- 0.70710677, 0.70710677, 1.]
- res = np.array([a, a]).T
+ asig2ch.window_op(nperseg=2, stride=1, win="hann", fn="rms", pad="mirror")
+ a = [
+ 1.0,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 0.70710677,
+ 1.0,
+ ]
+ _ = np.array([a, a]).T
self.assertTrue(np.allclose(a, asig_windowed.sig))
def test_convolve(self):
- # Do self autocorrelatin, the middle point should always have a corr val near 1.0
+ # Do self autocorrelation, the middle point
+ # should always have a corr val near 1.0
test = Asig(np.sin(np.arange(0, 21)), sr=21)
- result = test.convolve(test.sig[::-1], mode='same')
+ result = test.convolve(test.sig[::-1], mode="same")
# The middle point should have high corr
- self.assertTrue(result.sig[10] > 0.99, msg="middle point of a self correlation should always has high corr val.")
+ self.assertTrue(
+ result.sig[10] > 0.99,
+ msg="middle point of a self correlation should always has high corr val.",
+ )
# Test different modes
- self.assertEqual(result.samples, test.samples, msg="'same' mode should result in the same size")
- result = test.convolve(test.sig[::-1], mode='full')
-
- self.assertEqual(result.samples, test.samples * 2 - 1, msg="full mode should have 2x - 1 samples.")
+ self.assertEqual(
+ result.samples,
+ test.samples,
+ msg="'same' mode should result in the same size",
+ )
+ result = test.convolve(test.sig[::-1], mode="full")
+
+ self.assertEqual(
+ result.samples,
+ test.samples * 2 - 1,
+ msg="full mode should have 2x - 1 samples.",
+ )
# Test input type
ir = Asig(test.sig[::-1], sr=21)
- result = test.convolve(ir, mode='same')
- self.assertTrue(result.sig[10] > 0.99, msg="middle point of a self correlation should always has high corr val.")
+ result = test.convolve(ir, mode="same")
+ self.assertTrue(
+ result.sig[10] > 0.99,
+ msg="middle point of a self correlation should always has high corr val.",
+ )
with self.assertRaises(TypeError, msg="ins can only be array or Asig"):
result = test.convolve("string input")
@@ -256,7 +308,6 @@ def test_append(self):
# # At the top I import Asig by: from pya import Asig
@mock.patch("pya.asig.wavfile")
def test_save_wavefile(self, mock_wavfile):
-
test = Asig(np.array([0, 0.2, 0.4, 0.6, 0.8, 1.0]), sr=6)
test.save_wavfile(fname="mock save")
mock_wavfile.write.assert_called_once()
diff --git a/tests/test_aspec.py b/tests/test_aspec.py
index a11c9d68..4de7276e 100644
--- a/tests/test_aspec.py
+++ b/tests/test_aspec.py
@@ -1,14 +1,13 @@
-from unittest import TestCase
-from pya import Ugen, Aspec, Asig
import warnings
-import numpy as np
+from unittest import TestCase
+from pya import Aspec, Ugen
-class TestAspec(TestCase):
+class TestAspec(TestCase):
def setUp(self):
self.asig = Ugen().sine()
- self.asig2 = Ugen().sine(channels=2, cn=['a', 'b'])
+ self.asig2 = Ugen().sine(channels=2, cn=["a", "b"])
self.asig_no_name = Ugen().sine(channels=3)
def tearDown(self):
@@ -21,18 +20,18 @@ def test_constructor(self):
self.assertEqual(aspec.cn, self.asig2.cn)
# The input can also be just an numpy array
sig = Ugen().square().sig
- aspec = Aspec(sig, sr=400, label='square', cn=['a'])
+ aspec = Aspec(sig, sr=400, label="square", cn=["a"])
self.assertEqual(aspec.sr, 400)
- self.assertEqual(aspec.label, 'square')
- self.assertEqual(aspec.cn, ['a'])
+ self.assertEqual(aspec.label, "square")
+ self.assertEqual(aspec.cn, ["a"])
with self.assertRaises(TypeError):
_ = Aspec(x=3)
print(aspec)
def test_plot(self):
self.asig.to_spec().plot()
- self.asig.to_spec().plot(xlim=(0, 0.5), ylim=(0., 1.0))
+ self.asig.to_spec().plot(xlim=(0, 0.5), ylim=(0.0, 1.0))
def test_cn_conflict(self):
with warnings.catch_warnings(record=True):
- _ = Aspec(self.asig, cn=['jf', 'dj'])
+ _ = Aspec(self.asig, cn=["jf", "dj"])
diff --git a/tests/test_astft.py b/tests/test_astft.py
index 5b88538d..3980e996 100644
--- a/tests/test_astft.py
+++ b/tests/test_astft.py
@@ -1,17 +1,18 @@
from unittest import TestCase, mock
-from pya import Ugen, Astft
+
import numpy as np
+from pya import Astft, Ugen
+
class MockPlot(mock.MagicMock):
pass
class TestAstft(TestCase):
-
def setUp(self):
self.asig = Ugen().sine()
- self.asig2 = Ugen().sine(channels=2, cn=['a', 'b'])
+ self.asig2 = Ugen().sine(channels=2, cn=["a", "b"])
self.asig_no_name = Ugen().sine(channels=3)
def tearDown(self):
@@ -22,15 +23,15 @@ def test_input_as_asig(self):
self.assertEqual(astft.sr, 44100)
astft = self.asig.to_stft(sr=2000)
self.assertEqual(astft.sr, 2000)
- signal = self.asig2.sig
+ _ = self.asig2.sig
def test_wrong_input_type(self):
with self.assertRaises(TypeError):
- asig = Astft(x=3, sr=500)
+ _ = Astft(x=3, sr=500)
def test_multichannel_asig(self):
- # Test conversion of a multi channel asig's astft.
- asine = Ugen().sawtooth(channels=3, cn=['a', 'b', 'c'])
+ # Test conversion of a multi channel asig's astft.
+ asine = Ugen().sawtooth(channels=3, cn=["a", "b", "c"])
astft = asine.to_stft()
self.assertEqual(astft.channels, 3)
self.assertEqual(len(astft.cn), 3)
@@ -46,7 +47,7 @@ def test_input_as_stft(self):
noise = np.random.normal(scale=np.sqrt(noise_power), size=time.shape)
noise *= np.exp(-time / 5)
x = carrier + noise
- astft = Astft(x, sr, label="test")
+ _ = Astft(x, sr, label="test")
def test_plot(self):
- self.asig.to_stft().plot()
\ No newline at end of file
+ self.asig.to_stft().plot()
diff --git a/tests/test_backend.py b/tests/test_backend.py
index 594f661a..ef07db7b 100644
--- a/tests/test_backend.py
+++ b/tests/test_backend.py
@@ -1,26 +1,21 @@
-from .helpers import wait
-from .test_play import TestPlayBase
-from .test_arecorder import TestArecorderBase
-from pya import Arecorder
from pya.backend import DummyBackend
-from unittest import TestCase, skipUnless
+
+from .test_arecorder import TestArecorderBase
+from .test_play import TestPlayBase
try:
- from pya.backend import JupyterBackend
has_j_backend = True
-except:
+except Exception:
has_j_backend = False
# check if we have an output device
class TestDummyBackendPlay(TestPlayBase):
-
__test__ = True
backend = DummyBackend()
class TestDummyBackendRecord(TestArecorderBase):
-
__test__ = True
backend = DummyBackend()
diff --git a/tests/test_class_transformation.py b/tests/test_class_transformation.py
index 86897240..5159e04d 100644
--- a/tests/test_class_transformation.py
+++ b/tests/test_class_transformation.py
@@ -1,10 +1,10 @@
-# Test change between asig, astft and aspec.
-from pya import Asig, Aspec, Astft, Ugen
+# Test change between asig, astft and aspec.
from unittest import TestCase
+from pya import Asig, Aspec, Astft, Ugen
+
class TestClassTransform(TestCase):
-
def setUp(self):
pass
@@ -12,7 +12,7 @@ def tearDown(self):
pass
def test_asig_aspec(self):
- # Create a signale with 3 sine waves and gaps inbetween,
+ # Create a signale with 3 sine waves and gaps inbetween,
# So that it will finds 3 events
a = Ugen().sine()
a_spec = a.to_spec()
@@ -27,4 +27,4 @@ def test_asig_astf(self):
a_sig_from_stft = a_stft.to_sig()
self.assertIsInstance(a, Asig)
self.assertIsInstance(a_stft, Astft)
- self.assertIsInstance(a_sig_from_stft, Asig)
\ No newline at end of file
+ self.assertIsInstance(a_sig_from_stft, Asig)
diff --git a/tests/test_codestyle.py b/tests/test_codestyle.py
deleted file mode 100644
index 4c5bb354..00000000
--- a/tests/test_codestyle.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import unittest
-import pycodestyle
-
-
-class TestCodeFormat(unittest.TestCase):
-
- def test_conformance(self):
- """Test that we conform to PEP-8."""
- # E731 ignores lamda, W291 trailing whitespace
- # W391 blank line at end of file
- # W292 no newline at end of file
- # E722 bare except
- style = pycodestyle.StyleGuide(quiet=False,
- ignore=['E501', 'E731', 'W291', 'W504',
- 'W391', 'W292', 'E722', 'E402'])
- # style.input_dir('../../pya')
- style.input_dir('./pya')
- style.input_dir('./tests')
- result = style.check_files()
- self.assertEqual(0, result.total_errors,
- "Found code style errors (and warnings).")
diff --git a/tests/test_file_loader_codec.py b/tests/test_file_loader_codec.py
index 92fedaf5..83b6d36c 100644
--- a/tests/test_file_loader_codec.py
+++ b/tests/test_file_loader_codec.py
@@ -1,11 +1,13 @@
-from unittest import TestCase
import os
+from unittest import TestCase
+
import numpy as np
+
from pya.helper.codec import (
- audio_read,
- SoundFileAudioFile,
FFmpegAudioFile,
+ SoundFileAudioFile,
UnsupportedError,
+ audio_read,
)
@@ -96,7 +98,7 @@ def test_data_reading(self):
# TODO: Add a flac file for testing
# def test_high_resolution(self):
# """Test handling of high resolution audio (24-bit, high sample rate)"""
- # with audio_read(self.test_files['flac']) as audio: # Assuming 24-bit/96kHz FLAC
+ # with audio_read(self.test_files['flac']) as audio:# Assuming 24-bit/96kHz FLAC
# data = next(audio.read_data())
# self.assertTrue(np.max(np.abs(data)) <= 1.0) # Check normalization
# self.assertEqual(np.float32, data.dtype)
diff --git a/tests/test_find_events.py b/tests/test_find_events.py
index 6d59b58a..9140f762 100644
--- a/tests/test_find_events.py
+++ b/tests/test_find_events.py
@@ -1,9 +1,9 @@
-from pya import Asig, Ugen
from unittest import TestCase
+from pya import Asig, Ugen
+
class TestFindEvents(TestCase):
-
def setUp(self):
pass
@@ -11,13 +11,13 @@ def tearDown(self):
pass
def test_events(self):
- # Create a signale with 3 sine waves and
+ # Create a signale with 3 sine waves and
# gaps inbetween, So that it will finds 3 events"""
a = Ugen().sine()
- a.x[a.samples:] = Asig(0.2)
- a.x[a.samples:] = Ugen().sine(freq=200)
- a.x[a.samples:] = Asig(0.2)
- a.x[a.samples:] = Ugen().sine(freq=20)
- a.x[a.samples:] = Asig(0.2)
+ a.x[a.samples :] = Asig(0.2)
+ a.x[a.samples :] = Ugen().sine(freq=200)
+ a.x[a.samples :] = Asig(0.2)
+ a.x[a.samples :] = Ugen().sine(freq=20)
+ a.x[a.samples :] = Asig(0.2)
a.find_events(sil_thr=-30, evt_min_dur=0.2, sil_min_dur=0.04)
- self.assertEqual(3, a._['events'].shape[0])
+ self.assertEqual(3, a._["events"].shape[0])
diff --git a/tests/test_getitem.py b/tests/test_getitem.py
index 75626c86..c0289146 100644
--- a/tests/test_getitem.py
+++ b/tests/test_getitem.py
@@ -1,19 +1,23 @@
from unittest import TestCase
-from pya import *
+
import numpy as np
+
+from pya.asig import Asig
+
# import logging
# logging.basicConfig(level=logging.DEBUG)
class TestSlicing(TestCase):
-
def setUp(self):
self.sig = np.sin(2 * np.pi * 100 * np.linspace(0, 1, 44100))
self.asine = Asig(self.sig, sr=44100, label="test_sine")
- self.sig4 = np.sin(2 * np.pi * 100 * np.linspace(0, 4, 44100 * 4)) # 4second sine
+ self.sig4 = np.sin(
+ 2 * np.pi * 100 * np.linspace(0, 4, 44100 * 4)
+ ) # 4second sine
self.asine4 = Asig(self.sig4, sr=44100, label="test_sine")
self.sig2ch = np.repeat(self.sig, 2).reshape((44100, 2))
- self.astereo = Asig(self.sig2ch, sr=44100, label="stereo", cn=['l', 'r'])
+ self.astereo = Asig(self.sig2ch, sr=44100, label="stereo", cn=["l", "r"])
def tearDown(self):
pass
@@ -55,7 +59,7 @@ def test_timeSlicing(self):
# Check negative time work"""
result2 = self.asine4[{1: -1}] # Play from 1s. to the last 1.s
- expect2 = self.asine4[44100: -44100]
+ expect2 = self.asine4[44100:-44100]
self.assertEqual(expect2, result2)
def test_tuple(self):
@@ -64,32 +68,36 @@ def test_tuple(self):
expected_sig = self.astereo.sig[0:44100:2, 0]
self.assertTrue(np.array_equal(result.sig, expected_sig))
- result = self.astereo[0:10:2, ['l']]
+ result = self.astereo[0:10:2, ["l"]]
expected_sig = self.astereo.sig[0:10:2, 0]
- self.assertTrue(np.array_equal(result.sig, expected_sig)) # Check if signal equal
- self.assertEqual(result.cn, ['l']) # Check whether the new column name is correct
+ self.assertTrue(
+ np.array_equal(result.sig, expected_sig)
+ ) # Check if signal equal
+ self.assertEqual(
+ result.cn, ["l"]
+ ) # Check whether the new column name is correct
# channel name slice as list.
# ("both channels using col_name")
- result = self.astereo[0:44100:2, ['l', 'r']]
+ result = self.astereo[0:44100:2, ["l", "r"]]
expected_sig = self.astereo.sig[0:44100:2, :]
self.assertTrue(np.array_equal(result.sig, expected_sig))
# Bool slice
# ("bool list channel selection")
- # This is a special case for scling as numpy return (n, 1) rather than (n,) if we use
- # bool list to single out a channel.
+ # This is a special case for scling as numpy return (n, 1) rather than (n,)
+ # if we use bool list to single out a channel.
result = self.astereo[360:368, [False, True]]
expected_sig = self.astereo.sig[360:368:1, [False, True]]
self.assertTrue(np.array_equal(result.sig, expected_sig))
# time slicing
result = self.astereo[{1: -1}, 0] # Play from 1s. to the last 1.s
- expect = self.astereo[44100: -44100, 0]
+ expect = self.astereo[44100:-44100, 0]
self.assertEqual(expect, result)
# time slicing
# ("time slicing.")
- time_range = {1: -1} # first to last second.
- result = self.astereo[time_range, :] # Play from 1s. to the last 1.s
- expect = self.astereo[44100: -44100, :]
+ time_range = {1: -1} # first to last second.
+ result = self.astereo[time_range, :] # Play from 1s. to the last 1.s
+ expect = self.astereo[44100:-44100, :]
self.assertEqual(expect, result)
diff --git a/tests/test_helpers.py b/tests/test_helpers.py
index 41224a90..9e61b88c 100644
--- a/tests/test_helpers.py
+++ b/tests/test_helpers.py
@@ -1,34 +1,45 @@
from unittest import TestCase
-from pya import Asig, Ugen
-from pya.helper import spectrum, padding, next_pow2, is_pow2
-from pya.helper import signal_to_frame, magspec, powspec
import numpy as np
+from pya import Asig, Ugen
+from pya.helper import (
+ is_pow2,
+ magspec,
+ next_pow2,
+ padding,
+ powspec,
+ signal_to_frame,
+ spectrum,
+)
+
class TestHelpers(TestCase):
- """Test helper functions
- """
+ """Test helper functions"""
def setUp(self):
self.sig = np.sin(2 * np.pi * 100 * np.linspace(0, 1, 44100))
self.asine = Asig(self.sig, sr=44100, label="test_sine")
- self.asineWithName = Asig(self.sig, sr=44100,
- label="test_sine", cn=['sine'])
+ self.asineWithName = Asig(self.sig, sr=44100, label="test_sine", cn=["sine"])
self.sig2ch = np.repeat(self.sig, 2).reshape((44100, 2))
- self.astereo = Asig(self.sig2ch, sr=44100, label="sterep",
- cn=['l', 'r'])
+ self.astereo = Asig(self.sig2ch, sr=44100, label="sterep", cn=["l", "r"])
self.sig16ch = np.repeat(self.sig, 16).reshape((44100, 16))
- self.asine16ch = Asig(self.sig16ch, sr=44100,
- label="test_sine_16ch")
+ self.asine16ch = Asig(self.sig16ch, sr=44100, label="test_sine_16ch")
def tearDown(self):
pass
def test_spectrum(self):
# Not tested expected outcome yet.
- frq, Y = spectrum(self.asine.sig, self.asine.samples, self.asine.channels, self.asine.sr)
- frqs, Ys = spectrum(self.astereo.sig, self.astereo.samples, self.astereo.channels, self.astereo.sr)
+ frq, Y = spectrum(
+ self.asine.sig, self.asine.samples, self.asine.channels, self.asine.sr
+ )
+ frqs, Ys = spectrum(
+ self.astereo.sig,
+ self.astereo.samples,
+ self.astereo.channels,
+ self.astereo.sr,
+ )
def test_padding(self):
"""Pad silence to signal. Support 1-3D tensors."""
@@ -40,32 +51,61 @@ def test_padding(self):
tensor2 = np.ones((3, 3))
padded = padding(tensor2, 2, tail=True)
- self.assertTrue(np.array_equal(padded, np.array([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.],
- [0., 0., 0.], [0., 0., 0.]])))
+ self.assertTrue(
+ np.array_equal(
+ padded,
+ np.array(
+ [
+ [1.0, 1.0, 1.0],
+ [1.0, 1.0, 1.0],
+ [1.0, 1.0, 1.0],
+ [0.0, 0.0, 0.0],
+ [0.0, 0.0, 0.0],
+ ]
+ ),
+ )
+ )
padded = padding(tensor2, 2, tail=False, constant_values=5)
- self.assertTrue(np.array_equal(padded, np.array([[5., 5., 5.], [5., 5., 5.],
- [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]])))
+ self.assertTrue(
+ np.array_equal(
+ padded,
+ np.array(
+ [
+ [5.0, 5.0, 5.0],
+ [5.0, 5.0, 5.0],
+ [1.0, 1.0, 1.0],
+ [1.0, 1.0, 1.0],
+ [1.0, 1.0, 1.0],
+ ]
+ ),
+ )
+ )
tensor3 = np.ones((2, 2, 2))
padded = padding(tensor3, 2)
- self.assertTrue(np.array_equal(padded, np.array([[[1., 1.],
- [1., 1.],
- [0., 0.],
- [0., 0.]],
- [[1., 1.],
- [1., 1.],
- [0., 0.],
- [0., 0.]]])))
+ self.assertTrue(
+ np.array_equal(
+ padded,
+ np.array(
+ [
+ [[1.0, 1.0], [1.0, 1.0], [0.0, 0.0], [0.0, 0.0]],
+ [[1.0, 1.0], [1.0, 1.0], [0.0, 0.0], [0.0, 0.0]],
+ ]
+ ),
+ )
+ )
padded = padding(tensor3, 2, tail=False)
- self.assertTrue(np.array_equal(padded, np.array([[[0., 0.],
- [0., 0.],
- [1., 1.],
- [1., 1.]
- ],
- [[0., 0.],
- [0., 0.],
- [1., 1.],
- [1., 1.]]])))
+ self.assertTrue(
+ np.array_equal(
+ padded,
+ np.array(
+ [
+ [[0.0, 0.0], [0.0, 0.0], [1.0, 1.0], [1.0, 1.0]],
+ [[0.0, 0.0], [0.0, 0.0], [1.0, 1.0], [1.0, 1.0]],
+ ]
+ ),
+ )
+ )
def test_next_pow2(self):
next = next_pow2(255)
@@ -101,7 +141,7 @@ def test_magspec_pspec(self):
frames = signal_to_frame(sq.sig, 400, 400)
mag = magspec(frames, 512)
self.assertEqual(mag.shape, (20, 257))
- self.assertTrue((mag >= 0.).all()) # All elements should be non-negative
+ self.assertTrue((mag >= 0.0).all()) # All elements should be non-negative
ps = powspec(frames, 512)
self.assertEqual(ps.shape, (20, 257))
- self.assertTrue((ps >= 0.).all()) # All elements should be non-negative
+ self.assertTrue((ps >= 0.0).all()) # All elements should be non-negative
diff --git a/tests/test_play.py b/tests/test_play.py
index 39659da2..985c12b4 100644
--- a/tests/test_play.py
+++ b/tests/test_play.py
@@ -1,11 +1,13 @@
-from .helpers import check_for_output
import time
-from unittest import TestCase, skipUnless, mock
-from pya import *
+from unittest import TestCase, mock, skipUnless
+
import numpy as np
-import warnings
import pytest
+from pya.aserver import Aserver
+from pya.asig import Asig
+
+from .helpers import check_for_output
# check if we have an output device
has_output = check_for_output()
@@ -16,23 +18,29 @@ class MockAudio(mock.MagicMock):
channels_out = 4
def get_device_info_by_index(self, *args):
- return {'maxInputChannels': self.channels_in, 'maxOutputChannels': self.channels_out,
- 'name': 'MockAudio', 'index': 42}
+ return {
+ "maxInputChannels": self.channels_in,
+ "maxOutputChannels": self.channels_out,
+ "name": "MockAudio",
+ "index": 42,
+ }
class TestPlayBase(TestCase):
-
__test__ = False # important, makes sure tests are not run on base class
backend = None # will be overridden by backend tests
def setUp(self):
self.sig = np.sin(2 * np.pi * 440 * np.linspace(0, 1, 44100))
self.asine = Asig(self.sig, sr=44100, label="test_sine")
- self.asineWithName = Asig(self.sig, sr=44100, label="test_sine", cn=['sine'])
+ self.asineWithName = Asig(self.sig, sr=44100, label="test_sine", cn=["sine"])
self.sig2ch = np.repeat(self.sig, 2).reshape((44100, 2))
- self.astereo = Asig(self.sig2ch, sr=44100, label="stereo", cn=['l', 'r'])
+ self.astereo = Asig(self.sig2ch, sr=44100, label="stereo", cn=["l", "r"])
- @pytest.mark.xfail(reason="Test may get affect with PortAudio bug or potential unsuitable audio device.")
+ @pytest.mark.xfail(
+ reason="Test may get affect with PortAudio bug "
+ "or potential unsuitable audio device."
+ )
def test_play_and_stop(self):
ser = Aserver(backend=self.backend)
ser.boot()
@@ -44,21 +52,25 @@ def test_play_and_stop(self):
def test_gain(self):
result = (self.asine * 0.2).sig
expected = self.asine.sig * 0.2
- self.assertTrue(np.allclose(result, expected)) # float32 should use allclose for more forgiving precision
+ self.assertTrue(
+ np.allclose(result, expected)
+ ) # float32 should use allclose for more forgiving precision
expected = self.sig * self.sig
result = (self.asine * self.asine).sig
self.assertTrue(np.allclose(result, expected))
def test_resample(self):
- # This test currently only check if there is error running the code, but not whether resampling is correct
- result = self.asine.resample(target_sr=44100 // 2, rate=1, kind='linear')
+ """
+ This test currently only check if there is error
+ running the code, but not whether resampling is correct
+ """
+ result = self.asine.resample(target_sr=44100 // 2, rate=1, kind="linear")
self.assertIsInstance(result, Asig)
@skipUnless(has_output, "PyAudio found no output device.")
class TestPlay(TestPlayBase):
-
__test__ = True
@@ -72,7 +84,8 @@ class TestPlay(TestPlayBase):
# s = Aserver()
# s.boot()
# assert mock_audio.open.called
-# # since default AServer channel output is stereo we expect open to be called with
+# # since default AServer channel output is stereo we expect open to be
+# # called with
# # channels=2
# self.assertEqual(mock_audio.open.call_args_list[0][1]["channels"], 2)
# d1 = np.linspace(0, 1, 44100)
@@ -87,4 +100,3 @@ class TestPlay(TestPlayBase):
# s.boot()
# assert mock_audio.open.call_count == 2
# self.assertEqual(mock_audio.open.call_args_list[1][1]["channels"], 6)
-
diff --git a/tests/test_routeNpan.py b/tests/test_routeNpan.py
index 9305cc31..273760cf 100644
--- a/tests/test_routeNpan.py
+++ b/tests/test_routeNpan.py
@@ -1,7 +1,10 @@
-from unittest import TestCase
import warnings
+from unittest import TestCase
+
import numpy as np
-from pya import *
+
+from pya.asig import Asig
+
# import logging
# logging.basicConfig(level=logging.DEBUG)
@@ -12,9 +15,9 @@ class TestRoutePan(TestCase):
def setUp(self):
self.sig = np.sin(2 * np.pi * 100 * np.linspace(0, 1, 44100))
self.asine = Asig(self.sig, sr=44100, label="test_sine")
- self.asineWithName = Asig(self.sig, sr=44100, label="test_sine", cn=['sine'])
+ self.asineWithName = Asig(self.sig, sr=44100, label="test_sine", cn=["sine"])
self.sig2ch = np.repeat(self.sig, 2).reshape((44100, 2))
- self.astereo = Asig(self.sig2ch, sr=44100, label="sterep", cn=['l', 'r'])
+ self.astereo = Asig(self.sig2ch, sr=44100, label="sterep", cn=["l", "r"])
self.sig16ch = np.repeat(self.sig, 16).reshape((44100, 16))
self.asine16ch = Asig(self.sig16ch, sr=44100, label="test_sine_16ch")
@@ -51,8 +54,7 @@ def test_stereo(self):
def test_rewire(self):
# Rewire channels, e.g. move 0 to 1 with a gain of 0.5"""
- result = self.astereo.rewire({(0, 1): 0.5,
- (1, 0): 0.5})
+ result = self.astereo.rewire({(0, 1): 0.5, (1, 0): 0.5})
temp = self.astereo.sig
expect = temp.copy()
expect[:, 0] = temp[:, 1] * 0.5
@@ -60,14 +62,14 @@ def test_rewire(self):
self.assertTrue(np.allclose(expect[1000:10010, 1], result.sig[1000:10010, 1]))
def test_pan2(self):
- pan2 = self.astereo.pan2(-1.)
+ pan2 = self.astereo.pan2(-1.0)
self.assertAlmostEqual(0, pan2.sig[:, 1].sum())
- pan2 = self.astereo.pan2(1.)
+ pan2 = self.astereo.pan2(1.0)
self.assertAlmostEqual(0, pan2.sig[:, 0].sum())
pan2 = self.asine.pan2(-0.5)
self.assertEqual(pan2.channels, 2)
with self.assertRaises(TypeError):
- self.astereo.pan2([2., 4.])
+ self.astereo.pan2([2.0, 4.0])
with self.assertRaises(ValueError):
- self.astereo.pan2(3.)
\ No newline at end of file
+ self.astereo.pan2(3.0)
diff --git a/tests/test_setitem.py b/tests/test_setitem.py
index 0d2a0483..c6ceadd7 100644
--- a/tests/test_setitem.py
+++ b/tests/test_setitem.py
@@ -1,36 +1,42 @@
from unittest import TestCase
-from pya import *
+
import numpy as np
+
+from pya.asig import Asig
+
# import logging
# logging.basicConfig(level=logging.DEBUG)
class TestSetitem(TestCase):
-
def setUp(self):
self.dur = 3.5
self.sr = 1000
self.ts = np.linspace(0, self.dur, int(self.dur * self.sr))
- self.sig = np.sin(2 * np.pi * 50 * self.ts ** 1.9)
- self.a1 = Asig(self.sig, sr=self.sr, channels=1, cn=['a'], label='1ch-sig')
- self.ak = Asig(np.tile(self.sig.reshape(3500, 1), (1, 4)), sr=self.sr,
- label='4ch-sig', cn=['a', 'b', 'c', 'd'])
+ self.sig = np.sin(2 * np.pi * 50 * self.ts**1.9)
+ self.a1 = Asig(self.sig, sr=self.sr, channels=1, cn=["a"], label="1ch-sig")
+ self.ak = Asig(
+ np.tile(self.sig.reshape(3500, 1), (1, 4)),
+ sr=self.sr,
+ label="4ch-sig",
+ cn=["a", "b", "c", "d"],
+ )
self.one = np.ones(self.sr)
- self.aones = Asig(self.one, sr=self.sr, cn=['o'], label='ones')
+ self.aones = Asig(self.one, sr=self.sr, cn=["o"], label="ones")
self.zero = np.zeros(self.sr)
- self.azeros = Asig(self.zero, sr=self.sr, cn=['z'], label='zeros')
+ self.azeros = Asig(self.zero, sr=self.sr, cn=["z"], label="zeros")
self.noise = np.random.random(self.sr)
- self.anoise = Asig(self.noise, sr=self.sr, cn=['n'], label='noise')
- self.aramp = Asig(np.arange(1000), sr=self.sr, label='ramp')
+ self.anoise = Asig(self.noise, sr=self.sr, cn=["n"], label="noise")
+ self.aramp = Asig(np.arange(1000), sr=self.sr, label="ramp")
def tearDown(self):
pass
def test_default(self):
# Testing of default mode, which should behave as Numpy should."""
- self.azeros[10] = self.aones[10].sig # value as asig
+ self.azeros[10] = self.aones[10].sig # value as asig
self.assertEqual(self.aones[10], self.azeros[10])
- self.azeros[2] = self.aones[4].sig # value as ndarray
+ self.azeros[2] = self.aones[4].sig # value as ndarray
self.assertEqual(self.aones[4], self.azeros[2])
self.azeros[3:6] = [1, 2, 3] # value as list
self.assertTrue(np.array_equal(self.azeros[3:6].sig, [1, 2, 3]))
@@ -40,8 +46,8 @@ def test_default(self):
r = self.azeros[:10] # value as asig
self.assertTrue(r, self.azeros[:10])
self.azeros[{0.2: 0.4}] = self.anoise[{0.5: 0.7}]
- self.ak[{1: 2}, ['d']] = self.ak[{0: 1}, ['a']]
- self.assertTrue(np.array_equal(self.ak[{1: 2}, ['d']], self.ak[{0: 1}, ['a']]))
+ self.ak[{1: 2}, ["d"]] = self.ak[{0: 1}, ["a"]]
+ self.assertTrue(np.array_equal(self.ak[{1: 2}, ["d"]], self.ak[{0: 1}, ["a"]]))
def test_bound(self):
# Testing of bound mode. Redundant array will not be assigned"""
@@ -55,19 +61,21 @@ def test_bound(self):
result = np.arange(1000)[-10:] + np.arange(10)
self.assertTrue(np.array_equal(subject[-10:].sig, result))
- subject = Asig(np.arange(1000), sr=self.sr, label='ramp')
- subject.b[-10:] *= 2 # Test __mul__ also.
+ subject = Asig(np.arange(1000), sr=self.sr, label="ramp")
+ subject.b[-10:] *= 2 # Test __mul__ also.
result = np.arange(1000)[-10:] * 2
self.assertTrue(np.array_equal(subject[-10:].sig, result))
# # Multi channel case
- self.ak.b[{2: None}, ['a', 'b']] = np.zeros(shape=(3000, 2))
- result = np.sum(self.ak[{2: None}, ['a', 'b']].sig)
+ self.ak.b[{2: None}, ["a", "b"]] = np.zeros(shape=(3000, 2))
+ result = np.sum(self.ak[{2: None}, ["a", "b"]].sig)
self.assertEqual(result, 0.0)
def test_extend(self):
- # Testing of extend mode, longer array will force the taker to extend its shape."""
- a = Asig(0.8, sr=1000, channels=4, cn=['a', 'b', 'c', 'd'])
+ """
+ Testing of extend mode, longer array will force the taker to extend its shape.
+ """
+ a = Asig(0.8, sr=1000, channels=4, cn=["a", "b", "c", "d"])
b = np.sin(2 * np.pi * 100 * np.linspace(0, 0.6, int(1000 * 0.6)))
b = Asig(b)
# test with extend set mono signal to a, initially only 0.8secs long...
@@ -75,12 +83,12 @@ def test_extend(self):
self.assertEqual(a.samples, 800)
a.x[300:, 1] = 0.5 * b
self.assertEqual(a.samples, 900)
- a.x[1300:, 'c'] = 0.2 * b[::2] # compressed sig in ch 'c'
+ a.x[1300:, "c"] = 0.2 * b[::2] # compressed sig in ch 'c'
self.assertEqual(a.samples, 1600)
a.x[1900:, 3] = 0.2 * b[300:] # only end of tone in ch 'd'
self.assertEqual(a.samples, 2200)
- a = Asig(0.8, sr=1000, channels=1, cn=['a']) # Test with mono signal
+ a = Asig(0.8, sr=1000, channels=1, cn=["a"]) # Test with mono signal
b = np.sin(2 * np.pi * 100 * np.linspace(0, 0.6, int(1000 * 0.6)))
b = Asig(b)
a.x[:, 0] = 0.2 * b # this fits in without need to extend
@@ -92,19 +100,25 @@ def test_replace(self):
a = Asig(a)
a.overwrite[40:50] = b
self.assertEqual(a.samples, 100 - 10 + 290) # First make sure size is correct
- c = np.sum(a[50:60].sig) # Then make sure replace value is correct
+ c = np.sum(a[50:60].sig) # Then make sure replace value is correct
self.assertEqual(c, 10)
with self.assertRaises(ValueError):
# Passing 2 chan to 4 chan asig should raise ValueError
- self.ak.overwrite[{1.: 1.5}] = np.zeros((int(44100 * 0.6), 2))
+ self.ak.overwrite[{1.0: 1.5}] = np.zeros((int(44100 * 0.6), 2))
def test_numpy_index(self):
self.azeros[np.arange(0, 10)] = np.ones(10)
- self.assertTrue(np.array_equal(self.azeros[np.arange(0, 10)].sig, self.aones[np.arange(0, 10)].sig))
+ self.assertTrue(
+ np.array_equal(
+ self.azeros[np.arange(0, 10)].sig, self.aones[np.arange(0, 10)].sig
+ )
+ )
def test_byte_index(self):
self.azeros[bytes([0, 1, 2])] = np.ones(3)
- self.assertTrue(np.array_equal(self.azeros[[0, 1, 2]].sig, self.aones[[0, 1, 2]].sig))
+ self.assertTrue(
+ np.array_equal(self.azeros[[0, 1, 2]].sig, self.aones[[0, 1, 2]].sig)
+ )
def test_asig_index(self):
self.azeros[self.aones.sig.astype(bool)] = self.aones.sig
diff --git a/tests/test_ugen.py b/tests/test_ugen.py
index d549ff97..1fce246e 100644
--- a/tests/test_ugen.py
+++ b/tests/test_ugen.py
@@ -1,7 +1,9 @@
from unittest import TestCase
-from pya import *
+
import numpy as np
+from pya.ugen import Ugen
+
class TestUgen(TestCase):
def setUp(self):
@@ -50,7 +52,7 @@ def test_noise(self):
white = Ugen().noise(
type="white", amp=0.2, dur=1.0, sr=1000, cn=["white"], label="white_noise"
)
- pink = Ugen().noise(type="pink")
+ _ = Ugen().noise(type="pink")
self.assertEqual(white.sr, 1000)
self.assertEqual(white.cn, ["white"])
self.assertEqual(white.label, "white_noise")
@@ -60,4 +62,4 @@ def test_noise(self):
def test_dur_n_rows_exception(self):
# An exception should be raised if both dur and n_rows are define.
with self.assertRaises(AttributeError):
- asig = Ugen().sine(dur=1.0, n_rows=400)
+ _ = Ugen().sine(dur=1.0, n_rows=400)
diff --git a/tests/test_visualization.py b/tests/test_visualization.py
index 6903c2eb..68c077de 100644
--- a/tests/test_visualization.py
+++ b/tests/test_visualization.py
@@ -1,9 +1,10 @@
from unittest import TestCase
-from pya import *
+from pya.helper.visualization import gridplot
+from pya.ugen import Ugen
-class TestVisualization(TestCase):
+class TestVisualization(TestCase):
def setUp(self):
self.asig = Ugen().sine()
self.aspec = self.asig.to_spec()
@@ -21,21 +22,21 @@ def test_asig_plot_args(self):
self.asig.plot(xlim=(0, 100), ylim=(0, 100))
def test_asig_fn_db(self):
- self.asig.plot(fn='db')
+ self.asig.plot(fn="db")
def test_asig_fn_nocallable(self):
with self.assertRaises(AttributeError):
- self.asig.plot(fn='something')
+ self.asig.plot(fn="something")
def test_asig_multichannels(self):
- sig2d = Ugen().sine(channels=4, cn=['a', 'b', 'c', 'd'])
+ sig2d = Ugen().sine(channels=4, cn=["a", "b", "c", "d"])
sig2d.plot()
def test_aspec_plot(self):
self.aspec.plot()
def tesst_aspec_plot_lim(self):
- self.aspect.plot(xlim=(0, 1.), ylim=(0, 100))
+ self.aspect.plot(xlim=(0, 1.0), ylim=(0, 100))
def test_gridplot(self):
_ = gridplot(self.alst)
diff --git a/tox.ini b/tox.ini
index 6361cbc8..d49c3769 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,17 +1,62 @@
+# Tox configuration file
+# Read more under https://tox.wiki/
+
[tox]
-envlist = py3, check-manifest
-
-[testenv]
-passenv = PULSE_SERVER
-deps=
- -rrequirements.txt
- -rrequirements_pyaudio.txt
- -rrequirements_remote.txt
- -rrequirements_test.txt
- coverage
-commands=
- pytest --doctest-modules --cov pya/ {posargs}
-
-[testenv:check-manifest]
-deps = check-manifest
-commands = check-manifest
+minversion = 3.24
+envlist = default
+
+
+[testenv:{tests}]
+description = Invoke pytest to run automated tests
+setenv =
+ TOXINIDIR = {toxinidir}
+skip_install = true
+allowlist_externals = uv
+commands =
+ uv run pytest {posargs}
+
+[testenv:{build,clean}]
+description =
+ build: Build the package in isolation according to PEP517, see https://github.com/pypa/build
+ clean: Remove old distribution files and temporary build artifacts (./build and ./dist)
+# https://setuptools.pypa.io/en/stable/build_meta.html#how-to-use-it
+skip_install = True
+allowlist_externals = uv
+changedir = {toxinidir}
+commands =
+ clean: python -c 'import shutil; [shutil.rmtree(p, True) for p in ("build", "dist", "docs/_build")]'
+ clean: python -c 'import pathlib, shutil; [shutil.rmtree(p, True) for p in pathlib.Path("src").glob("*.egg-info")]'
+ build: uv build {posargs}
+
+
+[testenv:{docs,doctests,linkcheck}]
+description =
+ docs: Invoke sphinx-build to build the docs
+ doctests: Invoke sphinx-build to run doctests
+ linkcheck: Check for broken links in the documentation
+allowlist_externals = uv
+setenv =
+ DOCSDIR = {toxinidir}/docs
+ BUILDDIR = {toxinidir}/docs/_build
+ docs: BUILD = html
+ doctests: BUILD = doctest
+ linkcheck: BUILD = linkcheck
+ # ^ requirements.txt shared with Read The Docs
+commands =
+ uv run sphinx-build -v --color -b {env:BUILD} -d "{env:BUILDDIR}/doctrees" "{env:DOCSDIR}" "{env:BUILDDIR}/{env:BUILD}" {posargs}
+
+
+[testenv:publish]
+description =
+ Publish the package you have been developing to a package index server.
+ By default, it uses testpypi. If you really want to publish your package
+ to be publicly accessible in PyPI, use the `-- --repository pypi` option.
+skip_install = True
+allowlist_externals = uv
+changedir = {toxinidir}
+passenv =
+ UV_PUBLISH_USERNAME
+ UV_PUBLISH_PASSWORD
+ UV_PUBLISH_URL
+commands =
+ uv publish {posargs}
diff --git a/uv.lock b/uv.lock
new file mode 100644
index 00000000..b6dd1e93
--- /dev/null
+++ b/uv.lock
@@ -0,0 +1,2998 @@
+version = 1
+revision = 1
+requires-python = ">=3.11"
+resolution-markers = [
+ "python_full_version >= '3.14'",
+ "python_full_version >= '3.12' and python_full_version < '3.14'",
+ "python_full_version < '3.12'",
+]
+
+[[package]]
+name = "alabaster"
+version = "0.7.16"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c9/3e/13dd8e5ed9094e734ac430b5d0eb4f2bb001708a8b7856cbf8e084e001ba/alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65", size = 23776 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/32/34/d4e1c02d3bee589efb5dfa17f88ea08bdb3e3eac12bc475462aec52ed223/alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92", size = 13511 },
+]
+
+[[package]]
+name = "anyio"
+version = "4.13.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "idna" },
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353 },
+]
+
+[[package]]
+name = "appnope"
+version = "0.1.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321 },
+]
+
+[[package]]
+name = "argon2-cffi"
+version = "25.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "argon2-cffi-bindings" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657 },
+]
+
+[[package]]
+name = "argon2-cffi-bindings"
+version = "25.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cffi" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393 },
+ { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328 },
+ { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269 },
+ { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558 },
+ { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364 },
+ { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637 },
+ { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934 },
+ { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158 },
+ { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597 },
+ { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231 },
+ { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121 },
+ { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177 },
+ { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090 },
+ { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246 },
+ { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126 },
+ { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343 },
+ { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777 },
+ { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180 },
+ { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715 },
+ { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149 },
+]
+
+[[package]]
+name = "arrow"
+version = "1.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "python-dateutil" },
+ { name = "tzdata" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797 },
+]
+
+[[package]]
+name = "asttokens"
+version = "3.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047 },
+]
+
+[[package]]
+name = "async-lru"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e8/1f/989ecfef8e64109a489fff357450cb73fa73a865a92bd8c272170a6922c2/async_lru-2.3.0.tar.gz", hash = "sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6", size = 16332 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl", hash = "sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315", size = 8403 },
+]
+
+[[package]]
+name = "attrs"
+version = "26.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548 },
+]
+
+[[package]]
+name = "babel"
+version = "2.18.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845 },
+]
+
+[[package]]
+name = "beautifulsoup4"
+version = "4.14.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "soupsieve" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721 },
+]
+
+[[package]]
+name = "bleach"
+version = "6.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "webencodings" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437 },
+]
+
+[package.optional-dependencies]
+css = [
+ { name = "tinycss2" },
+]
+
+[[package]]
+name = "cachetools"
+version = "7.0.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/7b/1755ed2c6bfabd1d98b37ae73152f8dcf94aa40fee119d163c19ed484704/cachetools-7.0.6.tar.gz", hash = "sha256:e5d524d36d65703a87243a26ff08ad84f73352adbeafb1cde81e207b456aaf24", size = 37526 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/fe/c4/cf76242a5da1410917107ff14551764aa405a5fd10cd10cf9a5ca8fa77f4/cachetools-7.0.6-py3-none-any.whl", hash = "sha256:4e94956cfdd3086f12042cdd29318f5ced3893014f7d0d059bf3ead3f85b7f8b", size = 13976 },
+]
+
+[[package]]
+name = "certifi"
+version = "2026.4.22"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707 },
+]
+
+[[package]]
+name = "cffi"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pycparser", marker = "implementation_name != 'PyPy'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344 },
+ { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560 },
+ { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613 },
+ { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476 },
+ { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374 },
+ { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597 },
+ { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574 },
+ { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971 },
+ { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972 },
+ { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078 },
+ { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076 },
+ { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820 },
+ { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635 },
+ { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271 },
+ { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048 },
+ { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529 },
+ { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097 },
+ { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983 },
+ { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519 },
+ { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572 },
+ { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963 },
+ { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361 },
+ { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932 },
+ { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557 },
+ { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762 },
+ { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230 },
+ { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043 },
+ { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446 },
+ { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101 },
+ { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948 },
+ { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422 },
+ { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499 },
+ { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928 },
+ { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302 },
+ { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909 },
+ { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402 },
+ { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780 },
+ { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320 },
+ { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487 },
+ { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049 },
+ { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793 },
+ { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300 },
+ { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244 },
+ { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828 },
+ { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926 },
+ { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328 },
+ { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650 },
+ { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687 },
+ { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773 },
+ { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013 },
+ { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593 },
+ { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354 },
+ { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480 },
+ { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584 },
+ { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443 },
+ { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437 },
+ { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487 },
+ { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726 },
+ { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195 },
+]
+
+[[package]]
+name = "cfgv"
+version = "3.5.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445 },
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.4.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7", size = 309705 },
+ { url = "https://files.pythonhosted.org/packages/5a/53/58c29116c340e5456724ecd2fff4196d236b98f3da97b404bc5e51ac3493/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7", size = 206419 },
+ { url = "https://files.pythonhosted.org/packages/b2/02/e8146dc6591a37a00e5144c63f29fb7c97a734ea8a111190783c0e60ab63/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e", size = 227901 },
+ { url = "https://files.pythonhosted.org/packages/fb/73/77486c4cd58f1267bf17db420e930c9afa1b3be3fe8c8b8ebbebc9624359/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c", size = 222742 },
+ { url = "https://files.pythonhosted.org/packages/a1/fa/f74eb381a7d94ded44739e9d94de18dc5edc9c17fb8c11f0a6890696c0a9/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df", size = 214061 },
+ { url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265", size = 199239 },
+ { url = "https://files.pythonhosted.org/packages/4c/3d/069e7184e2aa3b3cddc700e3dd267413dc259854adc3380421c805c6a17d/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4", size = 210173 },
+ { url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e", size = 209841 },
+ { url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38", size = 200304 },
+ { url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c", size = 229455 },
+ { url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b", size = 210036 },
+ { url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c", size = 224739 },
+ { url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d", size = 216277 },
+ { url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad", size = 147819 },
+ { url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00", size = 159281 },
+ { url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1", size = 147843 },
+ { url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46", size = 311328 },
+ { url = "https://files.pythonhosted.org/packages/f8/e3/0fadc706008ac9d7b9b5be6dc767c05f9d3e5df51744ce4cc9605de7b9f4/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2", size = 208061 },
+ { url = "https://files.pythonhosted.org/packages/42/f0/3dd1045c47f4a4604df85ec18ad093912ae1344ac706993aff91d38773a2/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b", size = 229031 },
+ { url = "https://files.pythonhosted.org/packages/dc/67/675a46eb016118a2fbde5a277a5d15f4f69d5f3f5f338e5ee2f8948fcf43/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a", size = 225239 },
+ { url = "https://files.pythonhosted.org/packages/4b/f8/d0118a2f5f23b02cd166fa385c60f9b0d4f9194f574e2b31cef350ad7223/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116", size = 216589 },
+ { url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb", size = 202733 },
+ { url = "https://files.pythonhosted.org/packages/6f/c0/7b1f943f7e87cc3db9626ba17807d042c38645f0a1d4415c7a14afb5591f/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1", size = 212652 },
+ { url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15", size = 211229 },
+ { url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5", size = 203552 },
+ { url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d", size = 230806 },
+ { url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7", size = 212316 },
+ { url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464", size = 227274 },
+ { url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49", size = 218468 },
+ { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460 },
+ { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330 },
+ { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828 },
+ { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627 },
+ { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008 },
+ { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303 },
+ { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282 },
+ { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595 },
+ { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986 },
+ { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711 },
+ { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036 },
+ { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998 },
+ { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056 },
+ { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537 },
+ { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176 },
+ { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723 },
+ { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085 },
+ { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819 },
+ { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915 },
+ { url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234 },
+ { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042 },
+ { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706 },
+ { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727 },
+ { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882 },
+ { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860 },
+ { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564 },
+ { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276 },
+ { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238 },
+ { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189 },
+ { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352 },
+ { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024 },
+ { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869 },
+ { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541 },
+ { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634 },
+ { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384 },
+ { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133 },
+ { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257 },
+ { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851 },
+ { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393 },
+ { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251 },
+ { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609 },
+ { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014 },
+ { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979 },
+ { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238 },
+ { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110 },
+ { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824 },
+ { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103 },
+ { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194 },
+ { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827 },
+ { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168 },
+ { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018 },
+ { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958 },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
+]
+
+[[package]]
+name = "comm"
+version = "0.2.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294 },
+]
+
+[[package]]
+name = "contourpy"
+version = "1.3.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773 },
+ { url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149 },
+ { url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222 },
+ { url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234 },
+ { url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555 },
+ { url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238 },
+ { url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218 },
+ { url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867 },
+ { url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff", size = 183677 },
+ { url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42", size = 225234 },
+ { url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470", size = 193123 },
+ { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419 },
+ { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979 },
+ { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653 },
+ { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536 },
+ { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397 },
+ { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601 },
+ { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288 },
+ { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386 },
+ { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018 },
+ { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567 },
+ { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655 },
+ { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257 },
+ { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034 },
+ { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672 },
+ { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234 },
+ { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169 },
+ { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859 },
+ { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062 },
+ { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932 },
+ { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024 },
+ { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578 },
+ { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524 },
+ { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730 },
+ { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897 },
+ { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751 },
+ { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486 },
+ { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106 },
+ { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548 },
+ { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297 },
+ { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023 },
+ { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157 },
+ { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570 },
+ { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713 },
+ { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189 },
+ { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251 },
+ { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810 },
+ { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871 },
+ { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264 },
+ { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819 },
+ { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650 },
+ { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833 },
+ { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692 },
+ { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424 },
+ { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300 },
+ { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769 },
+ { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892 },
+ { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748 },
+ { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554 },
+ { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118 },
+ { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555 },
+ { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295 },
+ { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027 },
+ { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428 },
+ { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331 },
+ { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831 },
+ { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809 },
+ { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593 },
+ { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202 },
+ { url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207 },
+ { url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77", size = 225315 },
+]
+
+[[package]]
+name = "coverage"
+version = "7.13.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9d/e0/70553e3000e345daff267cec284ce4cbf3fc141b6da229ac52775b5428f1/coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179", size = 915967 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4b/37/d24c8f8220ff07b839b2c043ea4903a33b0f455abe673ae3c03bbdb7f212/coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d", size = 219381 },
+ { url = "https://files.pythonhosted.org/packages/35/8b/cd129b0ca4afe886a6ce9d183c44d8301acbd4ef248622e7c49a23145605/coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587", size = 219880 },
+ { url = "https://files.pythonhosted.org/packages/55/2f/e0e5b237bffdb5d6c530ce87cc1d413a5b7d7dfd60fb067ad6d254c35c76/coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642", size = 250303 },
+ { url = "https://files.pythonhosted.org/packages/92/be/b1afb692be85b947f3401375851484496134c5554e67e822c35f28bf2fbc/coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b", size = 252218 },
+ { url = "https://files.pythonhosted.org/packages/da/69/2f47bb6fa1b8d1e3e5d0c4be8ccb4313c63d742476a619418f85740d597b/coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686", size = 254326 },
+ { url = "https://files.pythonhosted.org/packages/d5/d0/79db81da58965bd29dabc8f4ad2a2af70611a57cba9d1ec006f072f30a54/coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743", size = 256267 },
+ { url = "https://files.pythonhosted.org/packages/e5/32/d0d7cc8168f91ddab44c0ce4806b969df5f5fdfdbb568eaca2dbc2a04936/coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75", size = 250430 },
+ { url = "https://files.pythonhosted.org/packages/4d/06/a055311d891ddbe231cd69fdd20ea4be6e3603ffebddf8704b8ca8e10a3c/coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209", size = 252017 },
+ { url = "https://files.pythonhosted.org/packages/d6/f6/d0fd2d21e29a657b5f77a2fe7082e1568158340dceb941954f776dce1b7b/coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a", size = 250080 },
+ { url = "https://files.pythonhosted.org/packages/4e/ab/0d7fb2efc2e9a5eb7ddcc6e722f834a69b454b7e6e5888c3a8567ecffb31/coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e", size = 253843 },
+ { url = "https://files.pythonhosted.org/packages/ba/6f/7467b917bbf5408610178f62a49c0ed4377bb16c1657f689cc61470da8ce/coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd", size = 249802 },
+ { url = "https://files.pythonhosted.org/packages/75/2c/1172fb689df92135f5bfbbd69fc83017a76d24ea2e2f3a1154007e2fb9f8/coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8", size = 250707 },
+ { url = "https://files.pythonhosted.org/packages/67/21/9ac389377380a07884e3b48ba7a620fcd9dbfaf1d40565facdc6b36ec9ef/coverage-7.13.5-cp311-cp311-win32.whl", hash = "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf", size = 221880 },
+ { url = "https://files.pythonhosted.org/packages/af/7f/4cd8a92531253f9d7c1bbecd9fa1b472907fb54446ca768c59b531248dc5/coverage-7.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9", size = 222816 },
+ { url = "https://files.pythonhosted.org/packages/12/a6/1d3f6155fb0010ca68eba7fe48ca6c9da7385058b77a95848710ecf189b1/coverage-7.13.5-cp311-cp311-win_arm64.whl", hash = "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028", size = 221483 },
+ { url = "https://files.pythonhosted.org/packages/a0/c3/a396306ba7db865bf96fc1fb3b7fd29bcbf3d829df642e77b13555163cd6/coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01", size = 219554 },
+ { url = "https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422", size = 219908 },
+ { url = "https://files.pythonhosted.org/packages/29/72/20b917c6793af3a5ceb7fb9c50033f3ec7865f2911a1416b34a7cfa0813b/coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f", size = 251419 },
+ { url = "https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5", size = 254159 },
+ { url = "https://files.pythonhosted.org/packages/9d/00/7b0edcfe64e2ed4c0340dac14a52ad0f4c9bd0b8b5e531af7d55b703db7c/coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376", size = 255270 },
+ { url = "https://files.pythonhosted.org/packages/93/89/7ffc4ba0f5d0a55c1e84ea7cee39c9fc06af7b170513d83fbf3bbefce280/coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256", size = 257538 },
+ { url = "https://files.pythonhosted.org/packages/81/bd/73ddf85f93f7e6fa83e77ccecb6162d9415c79007b4bc124008a4995e4a7/coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c", size = 251821 },
+ { url = "https://files.pythonhosted.org/packages/a0/81/278aff4e8dec4926a0bcb9486320752811f543a3ce5b602cc7a29978d073/coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5", size = 253191 },
+ { url = "https://files.pythonhosted.org/packages/70/ee/fe1621488e2e0a58d7e94c4800f0d96f79671553488d401a612bebae324b/coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09", size = 251337 },
+ { url = "https://files.pythonhosted.org/packages/37/a6/f79fb37aa104b562207cc23cb5711ab6793608e246cae1e93f26b2236ed9/coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9", size = 255404 },
+ { url = "https://files.pythonhosted.org/packages/75/f0/ed15262a58ec81ce457ceb717b7f78752a1713556b19081b76e90896e8d4/coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf", size = 250903 },
+ { url = "https://files.pythonhosted.org/packages/0f/e9/9129958f20e7e9d4d56d51d42ccf708d15cac355ff4ac6e736e97a9393d2/coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c", size = 252780 },
+ { url = "https://files.pythonhosted.org/packages/a4/d7/0ad9b15812d81272db94379fe4c6df8fd17781cc7671fdfa30c76ba5ff7b/coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf", size = 222093 },
+ { url = "https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810", size = 222900 },
+ { url = "https://files.pythonhosted.org/packages/d4/fa/2238c2ad08e35cf4f020ea721f717e09ec3152aea75d191a7faf3ef009a8/coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de", size = 221515 },
+ { url = "https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1", size = 219576 },
+ { url = "https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3", size = 219942 },
+ { url = "https://files.pythonhosted.org/packages/5f/13/93419671cee82b780bab7ea96b67c8ef448f5f295f36bf5031154ec9a790/coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26", size = 250935 },
+ { url = "https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3", size = 253541 },
+ { url = "https://files.pythonhosted.org/packages/4e/5e/3ee3b835647be646dcf3c65a7c6c18f87c27326a858f72ab22c12730773d/coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b", size = 254780 },
+ { url = "https://files.pythonhosted.org/packages/44/b3/cb5bd1a04cfcc49ede6cd8409d80bee17661167686741e041abc7ee1b9a9/coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a", size = 256912 },
+ { url = "https://files.pythonhosted.org/packages/1b/66/c1dceb7b9714473800b075f5c8a84f4588f887a90eb8645282031676e242/coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969", size = 251165 },
+ { url = "https://files.pythonhosted.org/packages/b7/62/5502b73b97aa2e53ea22a39cf8649ff44827bef76d90bf638777daa27a9d/coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161", size = 252908 },
+ { url = "https://files.pythonhosted.org/packages/7d/37/7792c2d69854397ca77a55c4646e5897c467928b0e27f2d235d83b5d08c6/coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15", size = 250873 },
+ { url = "https://files.pythonhosted.org/packages/a3/23/bc866fb6163be52a8a9e5d708ba0d3b1283c12158cefca0a8bbb6e247a43/coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1", size = 255030 },
+ { url = "https://files.pythonhosted.org/packages/7d/8b/ef67e1c222ef49860701d346b8bbb70881bef283bd5f6cbba68a39a086c7/coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6", size = 250694 },
+ { url = "https://files.pythonhosted.org/packages/46/0d/866d1f74f0acddbb906db212e096dee77a8e2158ca5e6bb44729f9d93298/coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17", size = 252469 },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/be742fec31118f02ce42b21c6af187ad6a344fed546b56ca60caacc6a9a0/coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85", size = 222112 },
+ { url = "https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b", size = 222923 },
+ { url = "https://files.pythonhosted.org/packages/48/af/fea819c12a095781f6ccd504890aaddaf88b8fab263c4940e82c7b770124/coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664", size = 221540 },
+ { url = "https://files.pythonhosted.org/packages/23/d2/17879af479df7fbbd44bd528a31692a48f6b25055d16482fdf5cdb633805/coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d", size = 220262 },
+ { url = "https://files.pythonhosted.org/packages/5b/4c/d20e554f988c8f91d6a02c5118f9abbbf73a8768a3048cb4962230d5743f/coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0", size = 220617 },
+ { url = "https://files.pythonhosted.org/packages/29/9c/f9f5277b95184f764b24e7231e166dfdb5780a46d408a2ac665969416d61/coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806", size = 261912 },
+ { url = "https://files.pythonhosted.org/packages/d5/f6/7f1ab39393eeb50cfe4747ae8ef0e4fc564b989225aa1152e13a180d74f8/coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3", size = 263987 },
+ { url = "https://files.pythonhosted.org/packages/a0/d7/62c084fb489ed9c6fbdf57e006752e7c516ea46fd690e5ed8b8617c7d52e/coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9", size = 266416 },
+ { url = "https://files.pythonhosted.org/packages/a9/f6/df63d8660e1a0bff6125947afda112a0502736f470d62ca68b288ea762d8/coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd", size = 267558 },
+ { url = "https://files.pythonhosted.org/packages/5b/02/353ca81d36779bd108f6d384425f7139ac3c58c750dcfaafe5d0bee6436b/coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606", size = 261163 },
+ { url = "https://files.pythonhosted.org/packages/2c/16/2e79106d5749bcaf3aee6d309123548e3276517cd7851faa8da213bc61bf/coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e", size = 263981 },
+ { url = "https://files.pythonhosted.org/packages/29/c7/c29e0c59ffa6942030ae6f50b88ae49988e7e8da06de7ecdbf49c6d4feae/coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0", size = 261604 },
+ { url = "https://files.pythonhosted.org/packages/40/48/097cdc3db342f34006a308ab41c3a7c11c3f0d84750d340f45d88a782e00/coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87", size = 265321 },
+ { url = "https://files.pythonhosted.org/packages/bb/1f/4994af354689e14fd03a75f8ec85a9a68d94e0188bbdab3fc1516b55e512/coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479", size = 260502 },
+ { url = "https://files.pythonhosted.org/packages/22/c6/9bb9ef55903e628033560885f5c31aa227e46878118b63ab15dc7ba87797/coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2", size = 262688 },
+ { url = "https://files.pythonhosted.org/packages/14/4f/f5df9007e50b15e53e01edea486814783a7f019893733d9e4d6caad75557/coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a", size = 222788 },
+ { url = "https://files.pythonhosted.org/packages/e1/98/aa7fccaa97d0f3192bec013c4e6fd6d294a6ed44b640e6bb61f479e00ed5/coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819", size = 223851 },
+ { url = "https://files.pythonhosted.org/packages/3d/8b/e5c469f7352651e5f013198e9e21f97510b23de957dd06a84071683b4b60/coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911", size = 222104 },
+ { url = "https://files.pythonhosted.org/packages/8e/77/39703f0d1d4b478bfd30191d3c14f53caf596fac00efb3f8f6ee23646439/coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f", size = 219621 },
+ { url = "https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e", size = 219953 },
+ { url = "https://files.pythonhosted.org/packages/6a/6c/1f1917b01eb647c2f2adc9962bd66c79eb978951cab61bdc1acab3290c07/coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a", size = 250992 },
+ { url = "https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510", size = 253503 },
+ { url = "https://files.pythonhosted.org/packages/80/28/2a148a51e5907e504fa7b85490277734e6771d8844ebcc48764a15e28155/coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247", size = 254852 },
+ { url = "https://files.pythonhosted.org/packages/61/77/50e8d3d85cc0b7ebe09f30f151d670e302c7ff4a1bf6243f71dd8b0981fa/coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6", size = 257161 },
+ { url = "https://files.pythonhosted.org/packages/3b/c4/b5fd1d4b7bf8d0e75d997afd3925c59ba629fc8616f1b3aae7605132e256/coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0", size = 251021 },
+ { url = "https://files.pythonhosted.org/packages/f8/66/6ea21f910e92d69ef0b1c3346ea5922a51bad4446c9126db2ae96ee24c4c/coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882", size = 252858 },
+ { url = "https://files.pythonhosted.org/packages/9e/ea/879c83cb5d61aa2a35fb80e72715e92672daef8191b84911a643f533840c/coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740", size = 250823 },
+ { url = "https://files.pythonhosted.org/packages/8a/fb/616d95d3adb88b9803b275580bdeee8bd1b69a886d057652521f83d7322f/coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16", size = 255099 },
+ { url = "https://files.pythonhosted.org/packages/1c/93/25e6917c90ec1c9a56b0b26f6cad6408e5f13bb6b35d484a0d75c9cf000d/coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0", size = 250638 },
+ { url = "https://files.pythonhosted.org/packages/fc/7b/dc1776b0464145a929deed214aef9fb1493f159b59ff3c7eeeedf91eddd0/coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0", size = 252295 },
+ { url = "https://files.pythonhosted.org/packages/ea/fb/99cbbc56a26e07762a2740713f3c8f9f3f3106e3a3dd8cc4474954bccd34/coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc", size = 222360 },
+ { url = "https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633", size = 223174 },
+ { url = "https://files.pythonhosted.org/packages/2c/f2/24d84e1dfe70f8ac9fdf30d338239860d0d1d5da0bda528959d0ebc9da28/coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8", size = 221739 },
+ { url = "https://files.pythonhosted.org/packages/60/5b/4a168591057b3668c2428bff25dd3ebc21b629d666d90bcdfa0217940e84/coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b", size = 220351 },
+ { url = "https://files.pythonhosted.org/packages/f5/21/1fd5c4dbfe4a58b6b99649125635df46decdfd4a784c3cd6d410d303e370/coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c", size = 220612 },
+ { url = "https://files.pythonhosted.org/packages/d6/fe/2a924b3055a5e7e4512655a9d4609781b0d62334fa0140c3e742926834e2/coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9", size = 261985 },
+ { url = "https://files.pythonhosted.org/packages/d7/0d/c8928f2bd518c45990fe1a2ab8db42e914ef9b726c975facc4282578c3eb/coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29", size = 264107 },
+ { url = "https://files.pythonhosted.org/packages/ef/ae/4ae35bbd9a0af9d820362751f0766582833c211224b38665c0f8de3d487f/coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607", size = 266513 },
+ { url = "https://files.pythonhosted.org/packages/9c/20/d326174c55af36f74eac6ae781612d9492f060ce8244b570bb9d50d9d609/coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90", size = 267650 },
+ { url = "https://files.pythonhosted.org/packages/7a/5e/31484d62cbd0eabd3412e30d74386ece4a0837d4f6c3040a653878bfc019/coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3", size = 261089 },
+ { url = "https://files.pythonhosted.org/packages/e9/d8/49a72d6de146eebb0b7e48cc0f4bc2c0dd858e3d4790ab2b39a2872b62bd/coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab", size = 263982 },
+ { url = "https://files.pythonhosted.org/packages/06/3b/0351f1bd566e6e4dd39e978efe7958bde1d32f879e85589de147654f57bb/coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562", size = 261579 },
+ { url = "https://files.pythonhosted.org/packages/5d/ce/796a2a2f4017f554d7810f5c573449b35b1e46788424a548d4d19201b222/coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2", size = 265316 },
+ { url = "https://files.pythonhosted.org/packages/3d/16/d5ae91455541d1a78bc90abf495be600588aff8f6db5c8b0dae739fa39c9/coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea", size = 260427 },
+ { url = "https://files.pythonhosted.org/packages/48/11/07f413dba62db21fb3fad5d0de013a50e073cc4e2dc4306e770360f6dfc8/coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a", size = 262745 },
+ { url = "https://files.pythonhosted.org/packages/91/15/d792371332eb4663115becf4bad47e047d16234b1aff687b1b18c58d60ae/coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215", size = 223146 },
+ { url = "https://files.pythonhosted.org/packages/db/51/37221f59a111dca5e85be7dbf09696323b5b9f13ff65e0641d535ed06ea8/coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43", size = 224254 },
+ { url = "https://files.pythonhosted.org/packages/54/83/6acacc889de8987441aa7d5adfbdbf33d288dad28704a67e574f1df9bcbb/coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45", size = 222276 },
+ { url = "https://files.pythonhosted.org/packages/9e/ee/a4cf96b8ce1e566ed238f0659ac2d3f007ed1d14b181bcb684e19561a69a/coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61", size = 211346 },
+]
+
+[package.optional-dependencies]
+toml = [
+ { name = "tomli", marker = "python_full_version <= '3.11'" },
+]
+
+[[package]]
+name = "cycler"
+version = "0.12.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321 },
+]
+
+[[package]]
+name = "debugpy"
+version = "1.8.20"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e0/b7/cd8080344452e4874aae67c40d8940e2b4d47b01601a8fd9f44786c757c7/debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33", size = 1645207 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/51/56/c3baf5cbe4dd77427fd9aef99fcdade259ad128feeb8a786c246adb838e5/debugpy-1.8.20-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:eada6042ad88fa1571b74bd5402ee8b86eded7a8f7b827849761700aff171f1b", size = 2208318 },
+ { url = "https://files.pythonhosted.org/packages/9a/7d/4fa79a57a8e69fe0d9763e98d1110320f9ecd7f1f362572e3aafd7417c9d/debugpy-1.8.20-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:7de0b7dfeedc504421032afba845ae2a7bcc32ddfb07dae2c3ca5442f821c344", size = 3171493 },
+ { url = "https://files.pythonhosted.org/packages/7d/f2/1e8f8affe51e12a26f3a8a8a4277d6e60aa89d0a66512f63b1e799d424a4/debugpy-1.8.20-cp311-cp311-win32.whl", hash = "sha256:773e839380cf459caf73cc533ea45ec2737a5cc184cf1b3b796cd4fd98504fec", size = 5209240 },
+ { url = "https://files.pythonhosted.org/packages/d5/92/1cb532e88560cbee973396254b21bece8c5d7c2ece958a67afa08c9f10dc/debugpy-1.8.20-cp311-cp311-win_amd64.whl", hash = "sha256:1f7650546e0eded1902d0f6af28f787fa1f1dbdbc97ddabaf1cd963a405930cb", size = 5233481 },
+ { url = "https://files.pythonhosted.org/packages/14/57/7f34f4736bfb6e00f2e4c96351b07805d83c9a7b33d28580ae01374430f7/debugpy-1.8.20-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:4ae3135e2089905a916909ef31922b2d733d756f66d87345b3e5e52b7a55f13d", size = 2550686 },
+ { url = "https://files.pythonhosted.org/packages/ab/78/b193a3975ca34458f6f0e24aaf5c3e3da72f5401f6054c0dfd004b41726f/debugpy-1.8.20-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:88f47850a4284b88bd2bfee1f26132147d5d504e4e86c22485dfa44b97e19b4b", size = 4310588 },
+ { url = "https://files.pythonhosted.org/packages/c1/55/f14deb95eaf4f30f07ef4b90a8590fc05d9e04df85ee379712f6fb6736d7/debugpy-1.8.20-cp312-cp312-win32.whl", hash = "sha256:4057ac68f892064e5f98209ab582abfee3b543fb55d2e87610ddc133a954d390", size = 5331372 },
+ { url = "https://files.pythonhosted.org/packages/a1/39/2bef246368bd42f9bd7cba99844542b74b84dacbdbea0833e610f384fee8/debugpy-1.8.20-cp312-cp312-win_amd64.whl", hash = "sha256:a1a8f851e7cf171330679ef6997e9c579ef6dd33c9098458bd9986a0f4ca52e3", size = 5372835 },
+ { url = "https://files.pythonhosted.org/packages/15/e2/fc500524cc6f104a9d049abc85a0a8b3f0d14c0a39b9c140511c61e5b40b/debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a", size = 2539560 },
+ { url = "https://files.pythonhosted.org/packages/90/83/fb33dcea789ed6018f8da20c5a9bc9d82adc65c0c990faed43f7c955da46/debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf", size = 4293272 },
+ { url = "https://files.pythonhosted.org/packages/a6/25/b1e4a01bfb824d79a6af24b99ef291e24189080c93576dfd9b1a2815cd0f/debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393", size = 5331208 },
+ { url = "https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7", size = 5372930 },
+ { url = "https://files.pythonhosted.org/packages/33/2e/f6cb9a8a13f5058f0a20fe09711a7b726232cd5a78c6a7c05b2ec726cff9/debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173", size = 2538066 },
+ { url = "https://files.pythonhosted.org/packages/c5/56/6ddca50b53624e1ca3ce1d1e49ff22db46c47ea5fb4c0cc5c9b90a616364/debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad", size = 4269425 },
+ { url = "https://files.pythonhosted.org/packages/c5/d9/d64199c14a0d4c476df46c82470a3ce45c8d183a6796cfb5e66533b3663c/debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f", size = 5331407 },
+ { url = "https://files.pythonhosted.org/packages/e0/d9/1f07395b54413432624d61524dfd98c1a7c7827d2abfdb8829ac92638205/debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be", size = 5372521 },
+ { url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7", size = 5337658 },
+]
+
+[[package]]
+name = "decorator"
+version = "5.2.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190 },
+]
+
+[[package]]
+name = "defusedxml"
+version = "0.7.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604 },
+]
+
+[[package]]
+name = "distlib"
+version = "0.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047 },
+]
+
+[[package]]
+name = "docutils"
+version = "0.20.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/1f/53/a5da4f2c5739cf66290fac1431ee52aff6851c7c8ffd8264f13affd7bcdd/docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b", size = 2058365 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/26/87/f238c0670b94533ac0353a4e2a1a771a0cc73277b88bff23d3ae35a256c1/docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6", size = 572666 },
+]
+
+[[package]]
+name = "executing"
+version = "2.2.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317 },
+]
+
+[[package]]
+name = "fastjsonschema"
+version = "2.21.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024 },
+]
+
+[[package]]
+name = "filelock"
+version = "3.29.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812 },
+]
+
+[[package]]
+name = "fonttools"
+version = "4.62.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9a/08/7012b00a9a5874311b639c3920270c36ee0c445b69d9989a85e5c92ebcb0/fonttools-4.62.1.tar.gz", hash = "sha256:e54c75fd6041f1122476776880f7c3c3295ffa31962dc6ebe2543c00dca58b5d", size = 3580737 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/88/39/23ff32561ec8d45a4d48578b4d241369d9270dc50926c017570e60893701/fonttools-4.62.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:40975849bac44fb0b9253d77420c6d8b523ac4dcdcefeff6e4d706838a5b80f7", size = 2871039 },
+ { url = "https://files.pythonhosted.org/packages/24/7f/66d3f8a9338a9b67fe6e1739f47e1cd5cee78bd3bc1206ef9b0b982289a5/fonttools-4.62.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9dde91633f77fa576879a0c76b1d89de373cae751a98ddf0109d54e173b40f14", size = 2416346 },
+ { url = "https://files.pythonhosted.org/packages/aa/53/5276ceba7bff95da7793a07c5284e1da901cf00341ce5e2f3273056c0cca/fonttools-4.62.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6acb4109f8bee00fec985c8c7afb02299e35e9c94b57287f3ea542f28bd0b0a7", size = 5100897 },
+ { url = "https://files.pythonhosted.org/packages/cc/a1/40a5c4d8e28b0851d53a8eeeb46fbd73c325a2a9a165f290a5ed90e6c597/fonttools-4.62.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1c5c25671ce8805e0d080e2ffdeca7f1e86778c5cbfbeae86d7f866d8830517b", size = 5071078 },
+ { url = "https://files.pythonhosted.org/packages/e3/be/d378fca4c65ea1956fee6d90ace6e861776809cbbc5af22388a090c3c092/fonttools-4.62.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a5d8825e1140f04e6c99bb7d37a9e31c172f3bc208afbe02175339e699c710e1", size = 5076908 },
+ { url = "https://files.pythonhosted.org/packages/f8/d9/ae6a1d0693a4185a84605679c8a1f719a55df87b9c6e8e817bfdd9ef5936/fonttools-4.62.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:268abb1cb221e66c014acc234e872b7870d8b5d4657a83a8f4205094c32d2416", size = 5202275 },
+ { url = "https://files.pythonhosted.org/packages/54/6c/af95d9c4efb15cabff22642b608342f2bd67137eea6107202d91b5b03184/fonttools-4.62.1-cp311-cp311-win32.whl", hash = "sha256:942b03094d7edbb99bdf1ae7e9090898cad7bf9030b3d21f33d7072dbcb51a53", size = 2293075 },
+ { url = "https://files.pythonhosted.org/packages/d3/97/bf54c5b3f2be34e1f143e6db838dfdc54f2ffa3e68c738934c82f3b2a08d/fonttools-4.62.1-cp311-cp311-win_amd64.whl", hash = "sha256:e8514f4924375f77084e81467e63238b095abda5107620f49421c368a6017ed2", size = 2344593 },
+ { url = "https://files.pythonhosted.org/packages/47/d4/dbacced3953544b9a93088cc10ef2b596d348c983d5c67a404fa41ec51ba/fonttools-4.62.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:90365821debbd7db678809c7491ca4acd1e0779b9624cdc6ddaf1f31992bf974", size = 2870219 },
+ { url = "https://files.pythonhosted.org/packages/66/9e/a769c8e99b81e5a87ab7e5e7236684de4e96246aae17274e5347d11ebd78/fonttools-4.62.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12859ff0b47dd20f110804c3e0d0970f7b832f561630cd879969011541a464a9", size = 2414891 },
+ { url = "https://files.pythonhosted.org/packages/69/64/f19a9e3911968c37e1e620e14dfc5778299e1474f72f4e57c5ec771d9489/fonttools-4.62.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c125ffa00c3d9003cdaaf7f2c79e6e535628093e14b5de1dccb08859b680936", size = 5033197 },
+ { url = "https://files.pythonhosted.org/packages/9b/8a/99c8b3c3888c5c474c08dbfd7c8899786de9604b727fcefb055b42c84bba/fonttools-4.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:149f7d84afca659d1a97e39a4778794a2f83bf344c5ee5134e09995086cc2392", size = 4988768 },
+ { url = "https://files.pythonhosted.org/packages/d1/c6/0f904540d3e6ab463c1243a0d803504826a11604c72dd58c2949796a1762/fonttools-4.62.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0aa72c43a601cfa9273bb1ae0518f1acadc01ee181a6fc60cd758d7fdadffc04", size = 4971512 },
+ { url = "https://files.pythonhosted.org/packages/29/0b/5cbef6588dc9bd6b5c9ad6a4d5a8ca384d0cea089da31711bbeb4f9654a6/fonttools-4.62.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:19177c8d96c7c36359266e571c5173bcee9157b59cfc8cb0153c5673dc5a3a7d", size = 5122723 },
+ { url = "https://files.pythonhosted.org/packages/4a/47/b3a5342d381595ef439adec67848bed561ab7fdb1019fa522e82101b7d9c/fonttools-4.62.1-cp312-cp312-win32.whl", hash = "sha256:a24decd24d60744ee8b4679d38e88b8303d86772053afc29b19d23bb8207803c", size = 2281278 },
+ { url = "https://files.pythonhosted.org/packages/28/b1/0c2ab56a16f409c6c8a68816e6af707827ad5d629634691ff60a52879792/fonttools-4.62.1-cp312-cp312-win_amd64.whl", hash = "sha256:9e7863e10b3de72376280b515d35b14f5eeed639d1aa7824f4cf06779ec65e42", size = 2331414 },
+ { url = "https://files.pythonhosted.org/packages/3b/56/6f389de21c49555553d6a5aeed5ac9767631497ac836c4f076273d15bd72/fonttools-4.62.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c22b1014017111c401469e3acc5433e6acf6ebcc6aa9efb538a533c800971c79", size = 2865155 },
+ { url = "https://files.pythonhosted.org/packages/03/c5/0e3966edd5ec668d41dfe418787726752bc07e2f5fd8c8f208615e61fa89/fonttools-4.62.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68959f5fc58ed4599b44aad161c2837477d7f35f5f79402d97439974faebfebe", size = 2412802 },
+ { url = "https://files.pythonhosted.org/packages/52/94/e6ac4b44026de7786fe46e3bfa0c87e51d5d70a841054065d49cd62bb909/fonttools-4.62.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef46db46c9447103b8f3ff91e8ba009d5fe181b1920a83757a5762551e32bb68", size = 5013926 },
+ { url = "https://files.pythonhosted.org/packages/e2/98/8b1e801939839d405f1f122e7d175cebe9aeb4e114f95bfc45e3152af9a7/fonttools-4.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6706d1cb1d5e6251a97ad3c1b9347505c5615c112e66047abbef0f8545fa30d1", size = 4964575 },
+ { url = "https://files.pythonhosted.org/packages/46/76/7d051671e938b1881670528fec69cc4044315edd71a229c7fd712eaa5119/fonttools-4.62.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2e7abd2b1e11736f58c1de27819e1955a53267c21732e78243fa2fa2e5c1e069", size = 4953693 },
+ { url = "https://files.pythonhosted.org/packages/1f/ae/b41f8628ec0be3c1b934fc12b84f4576a5c646119db4d3bdd76a217c90b5/fonttools-4.62.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:403d28ce06ebfc547fbcb0cb8b7f7cc2f7a2d3e1a67ba9a34b14632df9e080f9", size = 5094920 },
+ { url = "https://files.pythonhosted.org/packages/f2/f6/53a1e9469331a23dcc400970a27a4caa3d9f6edbf5baab0260285238b884/fonttools-4.62.1-cp313-cp313-win32.whl", hash = "sha256:93c316e0f5301b2adbe6a5f658634307c096fd5aae60a5b3412e4f3e1728ab24", size = 2279928 },
+ { url = "https://files.pythonhosted.org/packages/38/60/35186529de1db3c01f5ad625bde07c1f576305eab6d86bbda4c58445f721/fonttools-4.62.1-cp313-cp313-win_amd64.whl", hash = "sha256:7aa21ff53e28a9c2157acbc44e5b401149d3c9178107130e82d74ceb500e5056", size = 2330514 },
+ { url = "https://files.pythonhosted.org/packages/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fa1d16210b6b10a826d71bed68dd9ec24a9e218d5a5e2797f37c573e7ec215ca", size = 2864442 },
+ { url = "https://files.pythonhosted.org/packages/4b/b2/e521803081f8dc35990816b82da6360fa668a21b44da4b53fc9e77efcd62/fonttools-4.62.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:aa69d10ed420d8121118e628ad47d86e4caa79ba37f968597b958f6cceab7eca", size = 2410901 },
+ { url = "https://files.pythonhosted.org/packages/00/a4/8c3511ff06e53110039358dbbdc1a65d72157a054638387aa2ada300a8b8/fonttools-4.62.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd13b7999d59c5eb1c2b442eb2d0c427cb517a0b7a1f5798fc5c9e003f5ff782", size = 4999608 },
+ { url = "https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8d337fdd49a79b0d51c4da87bc38169d21c3abbf0c1aa9367eff5c6656fb6dae", size = 4912726 },
+ { url = "https://files.pythonhosted.org/packages/70/b9/ac677cb07c24c685cf34f64e140617d58789d67a3dd524164b63648c6114/fonttools-4.62.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d241cdc4a67b5431c6d7f115fdf63335222414995e3a1df1a41e1182acd4bcc7", size = 4951422 },
+ { url = "https://files.pythonhosted.org/packages/e6/10/11c08419a14b85b7ca9a9faca321accccc8842dd9e0b1c8a72908de05945/fonttools-4.62.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c05557a78f8fa514da0f869556eeda40887a8abc77c76ee3f74cf241778afd5a", size = 5060979 },
+ { url = "https://files.pythonhosted.org/packages/4e/3c/12eea4a4cf054e7ab058ed5ceada43b46809fce2bf319017c4d63ae55bb4/fonttools-4.62.1-cp314-cp314-win32.whl", hash = "sha256:49a445d2f544ce4a69338694cad575ba97b9a75fff02720da0882d1a73f12800", size = 2283733 },
+ { url = "https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-win_amd64.whl", hash = "sha256:1eecc128c86c552fb963fe846ca4e011b1be053728f798185a1687502f6d398e", size = 2335663 },
+ { url = "https://files.pythonhosted.org/packages/42/c5/4d2ed3ca6e33617fc5624467da353337f06e7f637707478903c785bd8e20/fonttools-4.62.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:1596aeaddf7f78e21e68293c011316a25267b3effdaccaf4d59bc9159d681b82", size = 2947288 },
+ { url = "https://files.pythonhosted.org/packages/1f/e9/7ab11ddfda48ed0f89b13380e5595ba572619c27077be0b2c447a63ff351/fonttools-4.62.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8f8fca95d3bb3208f59626a4b0ea6e526ee51f5a8ad5d91821c165903e8d9260", size = 2449023 },
+ { url = "https://files.pythonhosted.org/packages/b2/10/a800fa090b5e8819942e54e19b55fc7c21fe14a08757c3aa3ca8db358939/fonttools-4.62.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee91628c08e76f77b533d65feb3fbe6d9dad699f95be51cf0d022db94089cdc4", size = 5137599 },
+ { url = "https://files.pythonhosted.org/packages/37/dc/8ccd45033fffd74deb6912fa1ca524643f584b94c87a16036855b498a1ed/fonttools-4.62.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5f37df1cac61d906e7b836abe356bc2f34c99d4477467755c216b72aa3dc748b", size = 4920933 },
+ { url = "https://files.pythonhosted.org/packages/99/eb/e618adefb839598d25ac8136cd577925d6c513dc0d931d93b8af956210f0/fonttools-4.62.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:92bb00a947e666169c99b43753c4305fc95a890a60ef3aeb2a6963e07902cc87", size = 5016232 },
+ { url = "https://files.pythonhosted.org/packages/d9/5f/9b5c9bfaa8ec82def8d8168c4f13615990d6ce5996fe52bd49bfb5e05134/fonttools-4.62.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:bdfe592802ef939a0e33106ea4a318eeb17822c7ee168c290273cbd5fabd746c", size = 5042987 },
+ { url = "https://files.pythonhosted.org/packages/90/aa/dfbbe24c6a6afc5c203d90cc0343e24bcbb09e76d67c4d6eef8c2558d7ba/fonttools-4.62.1-cp314-cp314t-win32.whl", hash = "sha256:b820fcb92d4655513d8402d5b219f94481c4443d825b4372c75a2072aa4b357a", size = 2348021 },
+ { url = "https://files.pythonhosted.org/packages/13/6f/ae9c4e4dd417948407b680855c2c7790efb52add6009aaecff1e3bc50e8e/fonttools-4.62.1-cp314-cp314t-win_amd64.whl", hash = "sha256:59b372b4f0e113d3746b88985f1c796e7bf830dd54b28374cd85c2b8acd7583e", size = 2414147 },
+ { url = "https://files.pythonhosted.org/packages/fd/ba/56147c165442cc5ba7e82ecf301c9a68353cede498185869e6e02b4c264f/fonttools-4.62.1-py3-none-any.whl", hash = "sha256:7487782e2113861f4ddcc07c3436450659e3caa5e470b27dc2177cade2d8e7fd", size = 1152647 },
+]
+
+[[package]]
+name = "fqdn"
+version = "1.5.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121 },
+]
+
+[[package]]
+name = "gevent"
+version = "26.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cffi", marker = "platform_python_implementation == 'CPython' and sys_platform == 'win32'" },
+ { name = "greenlet", marker = "platform_python_implementation == 'CPython'" },
+ { name = "zope-event" },
+ { name = "zope-interface" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/20/27/1062fa31333dc3428a1f5f33cd6598b0552165ba679ca3ba116de42c9e8e/gevent-26.4.0.tar.gz", hash = "sha256:288d03addfccf0d1c67268358b6759b04392bf3bc35d26f3d9a45c82899c292d", size = 6242440 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/12/0e/330c4788860520850b7f4c6f84dd8591df5172cfd3f2796c046704ee879e/gevent-26.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:201323a5fb9a0646a0c7b384395ca55d60ee83200677919229df0648c4b78e6c", size = 1767278 },
+ { url = "https://files.pythonhosted.org/packages/cf/27/717593d7cce74a2fd6bee0713793518e0398132303d5267f02dd587c5945/gevent-26.4.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:82d68a60a4207826db295b4e80a204c9d392ce78ccc15679195faeb9e29d8388", size = 1861609 },
+ { url = "https://files.pythonhosted.org/packages/fb/af/ce6d4d554d9afc354b46b78eccb032f6add4d27c3eadaa0201ee103fa831/gevent-26.4.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:35b037b415ed38369717800250fe5974249525953b46026bef9def20f946dfb0", size = 1803675 },
+ { url = "https://files.pythonhosted.org/packages/57/09/909166fff7d2ab9523e93bbd56e863df79a856b2857350218be83aef119d/gevent-26.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:6d973735d2067607a32cd182893978755eee829a0dc268087592d3b715e63fad", size = 2118034 },
+ { url = "https://files.pythonhosted.org/packages/83/6b/ab68e1cc09fd6dd7adb9e1c54a47c6328df20aa012ed75526a3244f2ad05/gevent-26.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4fbd3ff28a7babbfee750684c4f46ba6eedb3bce69365dd146726986b79fa6c1", size = 1777768 },
+ { url = "https://files.pythonhosted.org/packages/ff/d3/b75568e7206ea4b89a7e21750381aa4a6f9afcced41d5a80a72b5fcc6b87/gevent-26.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f0a03650ca60c4c5774cbe21333905b95f2f5abd98ea5a3dbf28d93f2a7a5a84", size = 2144355 },
+ { url = "https://files.pythonhosted.org/packages/f7/32/5f795143351bfbecd05467deec48ea75416bb90eb7a6dd042c7d7e5ec594/gevent-26.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d00d8c4ca1afab90e478b79679dd53787082c6da8d2f4fdc7667a4440d1e1a7a", size = 1676684 },
+ { url = "https://files.pythonhosted.org/packages/3d/16/131d3874f50974b355c90a061a12d3fe2292cde0f875a1fa3d8b224f1251/gevent-26.4.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:318a0a73f664113e8d86d0cb0e328e7650e2d7d9c2e045418ab6fb1285831ad3", size = 2928699 },
+ { url = "https://files.pythonhosted.org/packages/ea/8b/199e59b303adaff7f7365def9ab569c7ecd863363c974548bce3ddc2c89d/gevent-26.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:ce7aa033a3f68beb6732d1450a80c1af29e63e0c2d01abad7918cf2507f72fa6", size = 1783821 },
+ { url = "https://files.pythonhosted.org/packages/e2/2d/b8249c9bd3f386191311c3a9bec4068e192a3f9df2fad92a71a15265ba15/gevent-26.4.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:a1b897c952baefd72232efaeb3bdb1ca2fa7ae94cbfe68ac21201b03e843190a", size = 1879424 },
+ { url = "https://files.pythonhosted.org/packages/ef/89/59216985c1f2c11f2f28bbc88e583588ad44cdde823c530ad4e307be6612/gevent-26.4.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:7eef2ea508ce41795e20587a5fc868ae4919543097c81a40fbdfd65bc479f54f", size = 1830575 },
+ { url = "https://files.pythonhosted.org/packages/ee/a9/2d67d2b0aa0ca9d7bb7fe73c3bbb97b3695cb15c338a6ea7734f58da9add/gevent-26.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f7e12fdd28cc9f39a463d8df5172d698c64a8ed385a21d98e7092fd8308a139a", size = 2113898 },
+ { url = "https://files.pythonhosted.org/packages/95/a3/457d58d9b3e7da17c8456d841c37a32af8d231a1d71237ad201b19129317/gevent-26.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d48e3ee13d7678c24c22f19d441ad6bc220a79f23662d03ff36fae0d62efdb59", size = 1795890 },
+ { url = "https://files.pythonhosted.org/packages/a7/cc/cbe78f2626643b20275aaa41cd2cc45ba75056e3665bde36bc190af3cae0/gevent-26.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c58c8e034f94329be4dc0979fba3301005a433dbab42cea0b2c33fd736946872", size = 2139791 },
+ { url = "https://files.pythonhosted.org/packages/f6/df/7875e08b06a95f4577b71708ec470d029fadf873a66eb813a2861d79dfb5/gevent-26.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1c737e6ac6ce1398df0e3f41c58d982e397c993cbe73ac05b7edbe39e128c9cb", size = 1680530 },
+ { url = "https://files.pythonhosted.org/packages/3d/be/51809d98bb00846d7756a0b82625024f9302145f3d024846b43f05efeddb/gevent-26.4.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1fe581d41c63cd1d8b12c69561ce53a48ad0d8763b254740d7bfea997335a38c", size = 2951507 },
+ { url = "https://files.pythonhosted.org/packages/d6/86/89325a62a4e8cc1934e155b383b66491ed21d1e774b13d5054d51fa0ac81/gevent-26.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c503b0c0a681e795255a13e5bb4e41615c3b020c1db93b8dfa04cfeb8f19d5a9", size = 1786029 },
+ { url = "https://files.pythonhosted.org/packages/a3/ea/04d112844aa992da583cbd280f17a4ba097da338dab347efd0aa5e235645/gevent-26.4.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:684256c29e3e5d4d0c4d06b772d00574d0dc859dfbb2fd13d318c512b16e1f89", size = 1881326 },
+ { url = "https://files.pythonhosted.org/packages/a1/33/71900c5ba442f5df89456b6d9fdaa43da2ae7cdd937d8c5667b49323ceb4/gevent-26.4.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:73eafd06b158d511f1ec6e5902a45e0ae3b48e745f35e9df97d25f809f537d88", size = 1833123 },
+ { url = "https://files.pythonhosted.org/packages/d0/af/7df19c92e56842921f34787e1168c7afc52a23b0d1253bba99344809a935/gevent-26.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1a18e543c830a1c07a2efeb33786a57ccac360af70cb42bbaf5a6f5f7ca49300", size = 2114330 },
+ { url = "https://files.pythonhosted.org/packages/ca/0e/202694960f8d4dda68fd2a73bbcb8251e2d5308339924310ff1fff31bf7c/gevent-26.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:74f1e3a460c43aefcb4ff9ef91aac15abc0b42e5233771e1956574d14ba9cac6", size = 1798427 },
+ { url = "https://files.pythonhosted.org/packages/75/69/2d056b2a4e3ef1f65f94002725572d1e99163ff79231dbb68ad529e7cb9d/gevent-26.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:954258873ae0bcc97fb41e48db25284fb73454bfefe27db8ceb89225da5502fb", size = 2140100 },
+ { url = "https://files.pythonhosted.org/packages/fe/a0/1a7f64aa2476c2b44abaecca919a6561bda85234f99fc7ac3c66bcb93050/gevent-26.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:4a9a64c064457c1afaf93ee2815fe0f38be6ecbb92806a6a712f12afc3e26cf5", size = 1680206 },
+ { url = "https://files.pythonhosted.org/packages/7e/f3/64638a941988f09aa1816e2674eb1efb215b6fa64a97edef6e25177b0845/gevent-26.4.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:7ab0f183a6fd2369eef619832eef14f1f2f69c605163c3f2dc41deb799af4a71", size = 2967206 },
+ { url = "https://files.pythonhosted.org/packages/f6/70/a86be65a51d3ebb92c82a70adc9c5c32b1a9d9579120d0be1db7cf534ce0/gevent-26.4.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:7e5906860e632bf965e1966c57e6bfc19dcb79dc262f04fdb0a9d7c12147bf69", size = 1792916 },
+ { url = "https://files.pythonhosted.org/packages/40/92/18fdb4b28f20129395f1c041773adee99e7fc2bcfff216df93bfb80787d5/gevent-26.4.0-cp314-cp314-manylinux_2_28_ppc64le.whl", hash = "sha256:297a361071dc6708115d4544859321e93b02a6cd5823ba02c0a909530a519d45", size = 1886617 },
+ { url = "https://files.pythonhosted.org/packages/af/c9/d02222ecf79d10c8a0c2755661485395b58c4bfffaafd88bcc230ce392de/gevent-26.4.0-cp314-cp314-manylinux_2_28_s390x.whl", hash = "sha256:7e74f59e5c9011afa2a9cb7106bb9a59f2a1f74c3d7b272c1b852eb0bc0b8f90", size = 1837660 },
+ { url = "https://files.pythonhosted.org/packages/46/85/9376d125fa4f7b0f269925d0d622eda0ff8f8dfc8d0c097a096c511fc738/gevent-26.4.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:45d6010a6a981f5a2b3411c4e38fbe305a1b46e4b12db3b4914775927dea7ba4", size = 2119342 },
+ { url = "https://files.pythonhosted.org/packages/b1/c4/1fe2817daca8e97c365fd739dd4057f71cce26ef600fb8465deb8060c83c/gevent-26.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dc38137ba2f43794c488615aafa2eefd0cc142f484a8274d4c827ed7a031a1e2", size = 1805672 },
+ { url = "https://files.pythonhosted.org/packages/e7/cc/ccbcbd56e7e85482291fbb90a317f5febf630ec4174a91506f4167ba0912/gevent-26.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:29a225d2d4da37e20c7a246754a64442d0e43e4534b8cc764f89530bb22a4237", size = 2145594 },
+ { url = "https://files.pythonhosted.org/packages/8e/b9/7dd37b6001d16f692b1bfb6e68cad642beb38b34a753c29bbff312f46e4b/gevent-26.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:d1c08bc9bb6bd79732a26710a99588b5e9b67b668e165dd609704b876f41baab", size = 1703189 },
+]
+
+[[package]]
+name = "greenlet"
+version = "3.5.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/3c/3f/dbf99fb14bfeb88c28f16729215478c0e265cacd6dc22270c8f31bb6892f/greenlet-3.5.0.tar.gz", hash = "sha256:d419647372241bc68e957bf38d5c1f98852155e4146bd1e4121adea81f4f01e4", size = 196995 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8b/0f/a91f143f356523ff682309732b175765a9bc2836fd7c081c2c67fedc1ad4/greenlet-3.5.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8f1cc966c126639cd152fdaa52624d2655f492faa79e013fea161de3e6dda082", size = 284726 },
+ { url = "https://files.pythonhosted.org/packages/95/82/800646c7ffc5dbabd75ddd2f6b519bb898c0c9c969e5d0473bfe5d20bcce/greenlet-3.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:362624e6a8e5bca3b8233e45eef33903a100e9539a2b995c364d595dbc4018b3", size = 604264 },
+ { url = "https://files.pythonhosted.org/packages/ca/ac/354867c0bba812fc33b15bc55aedafedd0aee3c7dd91dfca22444157dc0c/greenlet-3.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5ecd83806b0f4c2f53b1018e0005cd82269ea01d42befc0368730028d850ed1c", size = 616099 },
+ { url = "https://files.pythonhosted.org/packages/c9/ab/192090c4a5b30df148c22bf4b8895457d739a7c7c5a7b9c41e5dd7f537f2/greenlet-3.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa94cb2288681e3a11645958f1871d48ee9211bd2f66628fdace505927d6e564", size = 623976 },
+ { url = "https://files.pythonhosted.org/packages/ff/b0/815bece7399e01cadb69014219eebd0042339875c59a59b0820a46ece356/greenlet-3.5.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ff251e9a0279522e62f6176412869395a64ddf2b5c5f782ff609a8216a4e662", size = 615198 },
+ { url = "https://files.pythonhosted.org/packages/24/11/05eb2b9b188c6df7d68a89c99134d644a7af616a40b9808e8e6ced315d5d/greenlet-3.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:64d6ac45f7271f48e45f67c95b54ef73534c52ec041fcda8edf520c6d811f4bc", size = 418379 },
+ { url = "https://files.pythonhosted.org/packages/10/80/3b2c0a895d6698f6ddb31b07942ebfa982f3e30888bc5546a5b5990de8b2/greenlet-3.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d874e79afd41a96e11ff4c5d0bc90a80973e476fda1c2c64985667397df432b", size = 1574927 },
+ { url = "https://files.pythonhosted.org/packages/44/0e/f354af514a4c61454dbc68e44d47544a5a4d6317e30b77ddfa3a09f4c5f3/greenlet-3.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0ed006e4b86c59de7467eb2601cd1b77b5a7d657d1ee55e30fe30d76451edba4", size = 1642683 },
+ { url = "https://files.pythonhosted.org/packages/fa/6a/87f38255201e993a1915265ebb80cd7c2c78b04a45744995abbf6b259fd8/greenlet-3.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:703cb211b820dbffbbc55a16bfc6e4583a6e6e990f33a119d2cc8b83211119c8", size = 238115 },
+ { url = "https://files.pythonhosted.org/packages/e3/f8/450fe3c5938fa737ea4d22699772e6e34e8e24431a47bf4e8a1ceed4a98e/greenlet-3.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:6c18dfb59c70f5a94acd271c72e90128c3c776e41e5f07767908c8c1b74ad339", size = 235017 },
+ { url = "https://files.pythonhosted.org/packages/ef/32/f2ce6d4cac3e55bc6173f92dbe627e782e1850f89d986c3606feb63aafa7/greenlet-3.5.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:db2910d3c809444e0a20147361f343fe2798e106af8d9d8506f5305302655a9f", size = 286228 },
+ { url = "https://files.pythonhosted.org/packages/b7/aa/caed9e5adf742315fc7be2a84196373aab4816e540e38ba0d76cb7584d68/greenlet-3.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ec9ea74e7268ace7f9aab1b1a4e730193fc661b39a993cd91c606c32d4a3628", size = 601775 },
+ { url = "https://files.pythonhosted.org/packages/c7/af/90ae08497400a941595d12774447f752d3dfe0fbb012e35b76bc5c0ff37e/greenlet-3.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54d243512da35485fc7a6bf3c178fdda6327a9d6506fcdd62b1abd1e41b2927b", size = 614436 },
+ { url = "https://files.pythonhosted.org/packages/3f/e9/4eeadf8cb3403ac274245ba75f07844abc7fa5f6787583fc9156ba741e0f/greenlet-3.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:41353ec2ecedf7aa8f682753a41919f8718031a6edac46b8d3dc7ed9e1ceb136", size = 620610 },
+ { url = "https://files.pythonhosted.org/packages/2b/e0/2e13df68f367e2f9960616927d60857dd7e56aaadd59a47c644216b2f920/greenlet-3.5.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d280a7f5c331622c69f97eb167f33577ff2d1df282c41cd15907fc0a3ca198c", size = 611388 },
+ { url = "https://files.pythonhosted.org/packages/ee/ef/f913b3c0eb7d26d86a2401c5e1546c9d46b657efee724b06f6f4ac5d8824/greenlet-3.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:58c1c374fe2b3d852f9b6b11a7dff4c85404e51b9a596fd9e89cf904eb09866d", size = 422775 },
+ { url = "https://files.pythonhosted.org/packages/82/f7/393c64055132ac0d488ef6be549253b7e6274194863967ddc0bc8f5b87b8/greenlet-3.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1eb67d5adefb5bd2e182d42678a328979a209e4e82eb93575708185d31d1f588", size = 1570768 },
+ { url = "https://files.pythonhosted.org/packages/b8/4b/eaf7735253522cf56d1b74d672a58f54fc114702ceaf05def59aae72f6e1/greenlet-3.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2628d6c86f6cb0cb45e0c3c54058bbec559f57eaae699447748cb3928150577e", size = 1635983 },
+ { url = "https://files.pythonhosted.org/packages/4c/fe/4fb3a0805bd5165da5ebf858da7cc01cce8061674106d2cf5bdab32cbfde/greenlet-3.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:d4d9f0624c775f2dfc56ba54d515a8c771044346852a918b405914f6b19d7fd8", size = 238840 },
+ { url = "https://files.pythonhosted.org/packages/cb/cb/baa584cb00532126ffe12d9787db0a60c5a4f55c27bfe2666df5d4c30a32/greenlet-3.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:83ed9f27f1680b50e89f40f6df348a290ea234b249a4003d366663a12eab94f2", size = 235615 },
+ { url = "https://files.pythonhosted.org/packages/0c/58/fc576f99037ce19c5aa16628e4c3226b6d1419f72a62c79f5f40576e6eb3/greenlet-3.5.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:5a5ed18de6a0f6cc7087f1563f6bd93fc7df1c19165ca01e9bde5a5dc281d106", size = 285066 },
+ { url = "https://files.pythonhosted.org/packages/4a/ba/b28ddbe6bfad6a8ac196ef0e8cff37bc65b79735995b9e410923fffeeb70/greenlet-3.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a717fbc46d8a354fa675f7c1e813485b6ba3885f9bef0cd56e5ba27d758ff5b", size = 604414 },
+ { url = "https://files.pythonhosted.org/packages/09/06/4b69f8f0b67603a8be2790e55107a190b376f2627fe0eaf5695d85ffb3cd/greenlet-3.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ddc090c5c1792b10246a78e8c2163ebbe04cf877f9d785c230a7b27b39ad038e", size = 617349 },
+ { url = "https://files.pythonhosted.org/packages/6a/15/a643b4ecd09969e30b8a150d5919960caae0abe4f5af75ab040b1ab85e78/greenlet-3.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4964101b8585c144cbda5532b1aa644255126c08a265dae90c16e7a0e63aaa9d", size = 623234 },
+ { url = "https://files.pythonhosted.org/packages/8a/17/a3918541fd0ddefe024a69de6d16aa7b46d36ac19562adaa63c7fa180eff/greenlet-3.5.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2094acd54b272cb6eae8c03dd87b3fa1820a4cef18d6889c378d503500a1dc13", size = 613927 },
+ { url = "https://files.pythonhosted.org/packages/77/18/3b13d5ef1275b0ffaf933b05efa21408ac4ca95823c7411d79682e4fdcff/greenlet-3.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:7022615368890680e67b9965d33f5773aade330d5343bbe25560135aaa849eae", size = 425243 },
+ { url = "https://files.pythonhosted.org/packages/ee/e1/bd0af6213c7dd33175d8a462d4c1fe1175124ebed4855bc1475a5b5242c2/greenlet-3.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5e05ba267789ea87b5a155cf0e810b1ab88bf18e9e8740813945ceb8ee4350ba", size = 1570893 },
+ { url = "https://files.pythonhosted.org/packages/9b/2a/0789702f864f5382cb476b93d7a9c823c10472658102ccd65f415747d2e2/greenlet-3.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0ecec963079cd58cbd14723582384f11f166fd58883c15dcbfb342e0bc9b5846", size = 1636060 },
+ { url = "https://files.pythonhosted.org/packages/b2/8f/22bf9df92bbff0eb07842b60f7e63bf7675a9742df628437a9f02d09137f/greenlet-3.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:728d9667d8f2f586644b748dbd9bb67e50d6a9381767d1357714ea6825bb3bf5", size = 238740 },
+ { url = "https://files.pythonhosted.org/packages/b6/b7/9c5c3d653bd4ff614277c049ac676422e2c557db47b4fe43e6313fc005dc/greenlet-3.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:47422135b1d308c14b2c6e758beedb1acd33bb91679f5670edf77bf46244722b", size = 235525 },
+ { url = "https://files.pythonhosted.org/packages/94/5e/a70f31e3e8d961c4ce589c15b28e4225d63704e431a23932a3808cbcc867/greenlet-3.5.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:f35807464c4c58c55f0d31dfa83c541a5615d825c2fe3d2b95360cf7c4e3c0a8", size = 285564 },
+ { url = "https://files.pythonhosted.org/packages/af/a6/046c0a28e21833e4086918218cfb3d8bed51c075a1b700f20b9d7861c0f4/greenlet-3.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55fa7ea52771be44af0de27d8b80c02cd18c2c3cddde6c847ecebdf72418b6a1", size = 651166 },
+ { url = "https://files.pythonhosted.org/packages/47/f8/4af27f71c5ff32a7fbc516adb46370d9c4ae2bc7bd3dc7d066ac542b4b15/greenlet-3.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a97e4821aa710603f94de0da25f25096454d78ffdace5dc77f3a006bc01abba3", size = 663792 },
+ { url = "https://files.pythonhosted.org/packages/fb/89/2dadb89793c37ee8b4c237857188293e9060dc085f19845c292e00f8e091/greenlet-3.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bf2d8a80bec89ab46221ae45c5373d5ba0bd36c19aa8508e85c6cd7e5106cd37", size = 668086 },
+ { url = "https://files.pythonhosted.org/packages/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f52a464e4ed91780bdfbbdd2b97197f3accaa629b98c200f4dffada759f3ae7", size = 660933 },
+ { url = "https://files.pythonhosted.org/packages/82/35/75722be7e26a2af4cbd2dc35b0ed382dacf9394b7e75551f76ed1abe87f2/greenlet-3.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:1bae92a1dd94c5f9d9493c3a212dd874c202442047cf96446412c862feca83a2", size = 470799 },
+ { url = "https://files.pythonhosted.org/packages/83/e4/b903e5a5fae1e8a28cdd32a0cfbfd560b668c25b692f67768822ddc5f40f/greenlet-3.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:762612baf1161ccb8437c0161c668a688223cba28e1bf038f4eb47b13e39ccdf", size = 1618401 },
+ { url = "https://files.pythonhosted.org/packages/0e/e3/5ec408a329acb854fb607a122e1ee5fb3ff649f9a97952948a90803c0d8e/greenlet-3.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:57a43c6079a89713522bc4bcb9f75070ecf5d3dbad7792bfe42239362cbf2a16", size = 1682038 },
+ { url = "https://files.pythonhosted.org/packages/91/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bc59be3945ae9750b9e7d45067d01ae3fe90ea5f9ade99239dabdd6e28a5033", size = 239835 },
+ { url = "https://files.pythonhosted.org/packages/4e/62/1c498375cee177b55d980c1db319f26470e5309e54698c8f8fc06c0fd539/greenlet-3.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:a96fcee45e03fe30a62669fd16ab5c9d3c172660d3085605cb1e2d1280d3c988", size = 236862 },
+ { url = "https://files.pythonhosted.org/packages/78/a8/4522939255bb5409af4e87132f915446bf3622c2c292d14d3c38d128ae82/greenlet-3.5.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:a10a732421ab4fec934783ce3e54763470d0181db6e3468f9103a275c3ed1853", size = 293614 },
+ { url = "https://files.pythonhosted.org/packages/15/5e/8744c52e2c027b5a8772a01561934c8835f869733e101f62075c60430340/greenlet-3.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7fc391b1566f2907d17aaebe78f8855dc45675159a775fcf9e61f8ee0078e87f", size = 650723 },
+ { url = "https://files.pythonhosted.org/packages/00/ef/7b4c39c03cf46ceca512c5d3f914afd85aa30b2cc9a93015b0dd73e4be6c/greenlet-3.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:680bd0e7ad5e8daa8a4aa89f68fd6adc834b8a8036dc256533f7e08f4a4b01f7", size = 656529 },
+ { url = "https://files.pythonhosted.org/packages/5f/5c/0602239503b124b70e39355cbdb39361ecfe65b87a5f2f63752c32f5286f/greenlet-3.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1aa4ce8debcd4ea7fb2e150f3036588c41493d1d52c43538924ae1819003f4ce", size = 657015 },
+ { url = "https://files.pythonhosted.org/packages/0b/b5/c7768f352f5c010f92064d0063f987e7dc0cd290a6d92a34109015ce4aa1/greenlet-3.5.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddb36c7d6c9c0a65f18c7258634e0c416c6ab59caac8c987b96f80c2ebda0112", size = 654364 },
+ { url = "https://files.pythonhosted.org/packages/38/51/8699f865f125dc952384cb432b0f7138aa4d8f2969a7d12d0df5b94d054d/greenlet-3.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:728a73687e39ae9ca34e4694cbf2f049d3fbc7174639468d0f67200a97d8f9e2", size = 488275 },
+ { url = "https://files.pythonhosted.org/packages/ef/d0/079ebe12e4b1fc758857ce5be1a5e73f06870f2101e52611d1e71925ce54/greenlet-3.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e5ddf316ced87539144621453c3aef229575825fe60c604e62bedc4003f372b2", size = 1614204 },
+ { url = "https://files.pythonhosted.org/packages/6d/89/6c2fb63df3596552d20e58fb4d96669243388cf680cff222758812c7bfaa/greenlet-3.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4a448128607be0de65342dc9b31be7f948ef4cc0bc8832069350abefd310a8f2", size = 1675480 },
+ { url = "https://files.pythonhosted.org/packages/15/32/77ee8a6c1564fc345a491a4e85b3bf360e4cf26eac98c4532d2fdb96e01f/greenlet-3.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d60097128cb0a1cab9ea541186ea13cd7b847b8449a7787c2e2350da0cb82d86", size = 245324 },
+]
+
+[[package]]
+name = "h11"
+version = "0.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515 },
+]
+
+[[package]]
+name = "httpcore"
+version = "1.0.9"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "h11" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784 },
+]
+
+[[package]]
+name = "httpx"
+version = "0.28.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+ { name = "certifi" },
+ { name = "httpcore" },
+ { name = "idna" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
+]
+
+[[package]]
+name = "identify"
+version = "2.6.19"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397 },
+]
+
+[[package]]
+name = "idna"
+version = "3.13"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ce/cc/762dfb036166873f0059f3b7de4565e1b5bc3d6f28a414c13da27e442f99/idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242", size = 194210 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629 },
+]
+
+[[package]]
+name = "imagesize"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/6c/e6/7bf14eeb8f8b7251141944835abd42eb20a658d89084b7e1f3e5fe394090/imagesize-2.0.0.tar.gz", hash = "sha256:8e8358c4a05c304f1fccf7ff96f036e7243a189e9e42e90851993c558cfe9ee3", size = 1773045 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5f/53/fb7122b71361a0d121b669dcf3d31244ef75badbbb724af388948de543e2/imagesize-2.0.0-py2.py3-none-any.whl", hash = "sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96", size = 9441 },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484 },
+]
+
+[[package]]
+name = "ipykernel"
+version = "7.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "appnope", marker = "sys_platform == 'darwin'" },
+ { name = "comm" },
+ { name = "debugpy" },
+ { name = "ipython" },
+ { name = "jupyter-client" },
+ { name = "jupyter-core" },
+ { name = "matplotlib-inline" },
+ { name = "nest-asyncio" },
+ { name = "packaging" },
+ { name = "psutil" },
+ { name = "pyzmq" },
+ { name = "tornado" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ca/8d/b68b728e2d06b9e0051019640a40a9eb7a88fcd82c2e1b5ce70bef5ff044/ipykernel-7.2.0.tar.gz", hash = "sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e", size = 176046 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl", hash = "sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661", size = 118788 },
+]
+
+[[package]]
+name = "ipython"
+version = "9.13.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "decorator" },
+ { name = "ipython-pygments-lexers" },
+ { name = "jedi" },
+ { name = "matplotlib-inline" },
+ { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
+ { name = "prompt-toolkit" },
+ { name = "psutil" },
+ { name = "pygments" },
+ { name = "stack-data" },
+ { name = "traitlets" },
+ { name = "typing-extensions", marker = "python_full_version < '3.12'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/87cda5842cf5c31837c06ddb588e11c3c35d8ece89b7a0108c06b8c9b00a/ipython-9.13.0.tar.gz", hash = "sha256:7e834b6afc99f020e3f05966ced34792f40267d64cb1ea9043886dab0dde5967", size = 4430549 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b9/86/3060e8029b7cc505cce9a0137431dda81d0a3fde93a8f0f50ee0bf37a795/ipython-9.13.0-py3-none-any.whl", hash = "sha256:57f9d4639e20818d328d287c7b549af3d05f12486ea8f2e7f73e52a36ec4d201", size = 627274 },
+]
+
+[[package]]
+name = "ipython-pygments-lexers"
+version = "1.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074 },
+]
+
+[[package]]
+name = "ipywidgets"
+version = "8.1.8"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "comm" },
+ { name = "ipython" },
+ { name = "jupyterlab-widgets" },
+ { name = "traitlets" },
+ { name = "widgetsnbextension" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/4c/ae/c5ce1edc1afe042eadb445e95b0671b03cee61895264357956e61c0d2ac0/ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668", size = 116739 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e", size = 139808 },
+]
+
+[[package]]
+name = "isoduration"
+version = "20.11.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "arrow" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321 },
+]
+
+[[package]]
+name = "jedi"
+version = "0.19.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "parso" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278 },
+]
+
+[[package]]
+name = "jinja2"
+version = "3.1.6"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markupsafe" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 },
+]
+
+[[package]]
+name = "json5"
+version = "0.14.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9c/4b/6f8906aaf67d501e259b0adab4d312945bb7211e8b8d4dcc77c92320edaa/json5-0.14.0.tar.gz", hash = "sha256:b3f492fad9f6cdbced8b7d40b28b9b1c9701c5f561bef0d33b81c2ff433fefcb", size = 52656 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b8/42/cf027b4ac873b076189d935b135397675dac80cb29acb13e1ab86ad6c631/json5-0.14.0-py3-none-any.whl", hash = "sha256:56cf861bab076b1178eb8c92e1311d273a9b9acea2ccc82c276abf839ebaef3a", size = 36271 },
+]
+
+[[package]]
+name = "jsonpointer"
+version = "3.1.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659 },
+]
+
+[[package]]
+name = "jsonschema"
+version = "4.26.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "jsonschema-specifications" },
+ { name = "referencing" },
+ { name = "rpds-py" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630 },
+]
+
+[package.optional-dependencies]
+format-nongpl = [
+ { name = "fqdn" },
+ { name = "idna" },
+ { name = "isoduration" },
+ { name = "jsonpointer" },
+ { name = "rfc3339-validator" },
+ { name = "rfc3986-validator" },
+ { name = "rfc3987-syntax" },
+ { name = "uri-template" },
+ { name = "webcolors" },
+]
+
+[[package]]
+name = "jsonschema-specifications"
+version = "2025.9.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "referencing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437 },
+]
+
+[[package]]
+name = "jupyter-client"
+version = "8.8.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jupyter-core" },
+ { name = "python-dateutil" },
+ { name = "pyzmq" },
+ { name = "tornado" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371 },
+]
+
+[[package]]
+name = "jupyter-core"
+version = "5.9.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "platformdirs" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032 },
+]
+
+[[package]]
+name = "jupyter-events"
+version = "0.12.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jsonschema", extra = ["format-nongpl"] },
+ { name = "packaging" },
+ { name = "python-json-logger" },
+ { name = "pyyaml" },
+ { name = "referencing" },
+ { name = "rfc3339-validator" },
+ { name = "rfc3986-validator" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/18/f8/475c4241b2b75af0deaae453ed003c6c851766dbc44d332d8baf245dc931/jupyter_events-0.12.1.tar.gz", hash = "sha256:faff25f77218335752f35f23c5fe6e4a392a7bd99a5939ccb9b8fbf594636cf3", size = 62854 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/eb/6c/6fcde0c8f616ed360ffd3587f7db9e225a7e62b583a04494d2f069cf64ea/jupyter_events-0.12.1-py3-none-any.whl", hash = "sha256:c366585253f537a627da52fa7ca7410c5b5301fe893f511e7b077c2d93ec8bcf", size = 19512 },
+]
+
+[[package]]
+name = "jupyter-lsp"
+version = "2.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jupyter-server" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/36/ff/1e4a61f5170a9a1d978f3ac3872449de6c01fc71eaf89657824c878b1549/jupyter_lsp-2.3.1.tar.gz", hash = "sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6", size = 55677 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/23/e8/9d61dcbd1dce8ef418f06befd4ac084b4720429c26b0b1222bc218685eff/jupyter_lsp-2.3.1-py3-none-any.whl", hash = "sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81", size = 77513 },
+]
+
+[[package]]
+name = "jupyter-server"
+version = "2.17.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+ { name = "argon2-cffi" },
+ { name = "jinja2" },
+ { name = "jupyter-client" },
+ { name = "jupyter-core" },
+ { name = "jupyter-events" },
+ { name = "jupyter-server-terminals" },
+ { name = "nbconvert" },
+ { name = "nbformat" },
+ { name = "overrides", marker = "python_full_version < '3.12'" },
+ { name = "packaging" },
+ { name = "prometheus-client" },
+ { name = "pywinpty", marker = "os_name == 'nt'" },
+ { name = "pyzmq" },
+ { name = "send2trash" },
+ { name = "terminado" },
+ { name = "tornado" },
+ { name = "traitlets" },
+ { name = "websocket-client" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/5b/ac/e040ec363d7b6b1f11304cc9f209dac4517ece5d5e01821366b924a64a50/jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5", size = 731949 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f", size = 388221 },
+]
+
+[[package]]
+name = "jupyter-server-terminals"
+version = "0.5.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pywinpty", marker = "os_name == 'nt'" },
+ { name = "terminado" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704 },
+]
+
+[[package]]
+name = "jupyterlab"
+version = "4.5.7"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "async-lru" },
+ { name = "httpx" },
+ { name = "ipykernel" },
+ { name = "jinja2" },
+ { name = "jupyter-core" },
+ { name = "jupyter-lsp" },
+ { name = "jupyter-server" },
+ { name = "jupyterlab-server" },
+ { name = "notebook-shim" },
+ { name = "packaging" },
+ { name = "setuptools" },
+ { name = "tornado" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/2b/22/8440ec827762146e7cdecf04335bd348795899d29dc6ae82238707353a2c/jupyterlab-4.5.7.tar.gz", hash = "sha256:55a9822c4754da305f41e113452c68383e214dcf96de760146af89ce5d5117b0", size = 23992763 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3d/aa/537b8f7d80e799af19af35fb3ddfc970b951088a13c57dd9387dcfbb7f61/jupyterlab-4.5.7-py3-none-any.whl", hash = "sha256:fba4cb0e2c44a52859669d8c98b45de029d5e515f8407bf8534d2a8fc5f0964d", size = 12450123 },
+]
+
+[[package]]
+name = "jupyterlab-pygments"
+version = "0.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884 },
+]
+
+[[package]]
+name = "jupyterlab-server"
+version = "2.28.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "babel" },
+ { name = "jinja2" },
+ { name = "json5" },
+ { name = "jsonschema" },
+ { name = "jupyter-server" },
+ { name = "packaging" },
+ { name = "requests" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830 },
+]
+
+[[package]]
+name = "jupyterlab-widgets"
+version = "3.0.16"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/26/2d/ef58fed122b268c69c0aa099da20bc67657cdfb2e222688d5731bd5b971d/jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0", size = 897423 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8", size = 914926 },
+]
+
+[[package]]
+name = "kiwisolver"
+version = "1.5.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/12/dd/a495a9c104be1c476f0386e714252caf2b7eca883915422a64c50b88c6f5/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c", size = 122798 },
+ { url = "https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb", size = 66216 },
+ { url = "https://files.pythonhosted.org/packages/0a/aa/510dc933d87767584abfe03efa445889996c70c2990f6f87c3ebaa0a18c5/kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac", size = 63911 },
+ { url = "https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27", size = 1438209 },
+ { url = "https://files.pythonhosted.org/packages/fd/d6/76621246f5165e5372f02f5e6f3f48ea336a8f9e96e43997d45b240ed8cd/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398", size = 1248888 },
+ { url = "https://files.pythonhosted.org/packages/b2/c1/31559ec6fb39a5b48035ce29bb63ade628f321785f38c384dee3e2c08bc1/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db", size = 1266304 },
+ { url = "https://files.pythonhosted.org/packages/5e/ef/1cb8276f2d29cc6a41e0a042f27946ca347d3a4a75acf85d0a16aa6dcc82/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc", size = 1319650 },
+ { url = "https://files.pythonhosted.org/packages/4c/e4/5ba3cecd7ce6236ae4a80f67e5d5531287337d0e1f076ca87a5abe4cd5d0/kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679", size = 970949 },
+ { url = "https://files.pythonhosted.org/packages/5a/69/dc61f7ae9a2f071f26004ced87f078235b5507ab6e5acd78f40365655034/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309", size = 2199125 },
+ { url = "https://files.pythonhosted.org/packages/e5/7b/abbe0f1b5afa85f8d084b73e90e5f801c0939eba16ac2e49af7c61a6c28d/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2", size = 2293783 },
+ { url = "https://files.pythonhosted.org/packages/8a/80/5908ae149d96d81580d604c7f8aefd0e98f4fd728cf172f477e9f2a81744/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c", size = 1960726 },
+ { url = "https://files.pythonhosted.org/packages/84/08/a78cb776f8c085b7143142ce479859cfec086bd09ee638a317040b6ef420/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08", size = 2464738 },
+ { url = "https://files.pythonhosted.org/packages/b1/e1/65584da5356ed6cb12c63791a10b208860ac40a83de165cb6a6751a686e3/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4", size = 2270718 },
+ { url = "https://files.pythonhosted.org/packages/be/6c/28f17390b62b8f2f520e2915095b3c94d88681ecf0041e75389d9667f202/kiwisolver-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:beb7f344487cdcb9e1efe4b7a29681b74d34c08f0043a327a74da852a6749e7b", size = 73480 },
+ { url = "https://files.pythonhosted.org/packages/d8/0e/2ee5debc4f77a625778fec5501ff3e8036fe361b7ee28ae402a485bb9694/kiwisolver-1.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:ad4ae4ffd1ee9cd11357b4c66b612da9888f4f4daf2f36995eda64bd45370cac", size = 64930 },
+ { url = "https://files.pythonhosted.org/packages/4d/b2/818b74ebea34dabe6d0c51cb1c572e046730e64844da6ed646d5298c40ce/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9", size = 123158 },
+ { url = "https://files.pythonhosted.org/packages/bf/d9/405320f8077e8e1c5c4bd6adc45e1e6edf6d727b6da7f2e2533cf58bff71/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588", size = 66388 },
+ { url = "https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819", size = 64068 },
+ { url = "https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f", size = 1477934 },
+ { url = "https://files.pythonhosted.org/packages/c8/2f/cebfcdb60fd6a9b0f6b47a9337198bcbad6fbe15e68189b7011fd914911f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf", size = 1278537 },
+ { url = "https://files.pythonhosted.org/packages/f2/0d/9b782923aada3fafb1d6b84e13121954515c669b18af0c26e7d21f579855/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d", size = 1296685 },
+ { url = "https://files.pythonhosted.org/packages/27/70/83241b6634b04fe44e892688d5208332bde130f38e610c0418f9ede47ded/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083", size = 1346024 },
+ { url = "https://files.pythonhosted.org/packages/e4/db/30ed226fb271ae1a6431fc0fe0edffb2efe23cadb01e798caeb9f2ceae8f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6", size = 987241 },
+ { url = "https://files.pythonhosted.org/packages/ec/bd/c314595208e4c9587652d50959ead9e461995389664e490f4dce7ff0f782/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1", size = 2227742 },
+ { url = "https://files.pythonhosted.org/packages/c1/43/0499cec932d935229b5543d073c2b87c9c22846aab48881e9d8d6e742a2d/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0", size = 2323966 },
+ { url = "https://files.pythonhosted.org/packages/3d/6f/79b0d760907965acfd9d61826a3d41f8f093c538f55cd2633d3f0db269f6/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15", size = 1977417 },
+ { url = "https://files.pythonhosted.org/packages/ab/31/01d0537c41cb75a551a438c3c7a80d0c60d60b81f694dac83dd436aec0d0/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314", size = 2491238 },
+ { url = "https://files.pythonhosted.org/packages/e4/34/8aefdd0be9cfd00a44509251ba864f5caf2991e36772e61c408007e7f417/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9", size = 2294947 },
+ { url = "https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384", size = 73569 },
+ { url = "https://files.pythonhosted.org/packages/28/26/192b26196e2316e2bd29deef67e37cdf9870d9af8e085e521afff0fed526/kiwisolver-1.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7", size = 64997 },
+ { url = "https://files.pythonhosted.org/packages/9d/69/024d6711d5ba575aa65d5538042e99964104e97fa153a9f10bc369182bc2/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09", size = 123166 },
+ { url = "https://files.pythonhosted.org/packages/ce/48/adbb40df306f587054a348831220812b9b1d787aff714cfbc8556e38fccd/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3", size = 66395 },
+ { url = "https://files.pythonhosted.org/packages/a8/3a/d0a972b34e1c63e2409413104216cd1caa02c5a37cb668d1687d466c1c45/kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd", size = 64065 },
+ { url = "https://files.pythonhosted.org/packages/2b/0a/7b98e1e119878a27ba8618ca1e18b14f992ff1eda40f47bccccf4de44121/kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3", size = 1477903 },
+ { url = "https://files.pythonhosted.org/packages/18/d8/55638d89ffd27799d5cc3d8aa28e12f4ce7a64d67b285114dbedc8ea4136/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96", size = 1278751 },
+ { url = "https://files.pythonhosted.org/packages/b8/97/b4c8d0d18421ecceba20ad8701358453b88e32414e6f6950b5a4bad54e65/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099", size = 1296793 },
+ { url = "https://files.pythonhosted.org/packages/c4/10/f862f94b6389d8957448ec9df59450b81bec4abb318805375c401a1e6892/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8", size = 1346041 },
+ { url = "https://files.pythonhosted.org/packages/a3/6a/f1650af35821eaf09de398ec0bc2aefc8f211f0cda50204c9f1673741ba9/kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87", size = 987292 },
+ { url = "https://files.pythonhosted.org/packages/de/19/d7fb82984b9238115fe629c915007be608ebd23dc8629703d917dbfaffd4/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23", size = 2227865 },
+ { url = "https://files.pythonhosted.org/packages/7f/b9/46b7f386589fd222dac9e9de9c956ce5bcefe2ee73b4e79891381dda8654/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859", size = 2324369 },
+ { url = "https://files.pythonhosted.org/packages/92/8b/95e237cf3d9c642960153c769ddcbe278f182c8affb20cecc1cc983e7cc5/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902", size = 1977989 },
+ { url = "https://files.pythonhosted.org/packages/1b/95/980c9df53501892784997820136c01f62bc1865e31b82b9560f980c0e649/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167", size = 2491645 },
+ { url = "https://files.pythonhosted.org/packages/cb/32/900647fd0840abebe1561792c6b31e6a7c0e278fc3973d30572a965ca14c/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0", size = 2295237 },
+ { url = "https://files.pythonhosted.org/packages/be/8a/be60e3bbcf513cc5a50f4a3e88e1dcecebb79c1ad607a7222877becaa101/kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276", size = 73573 },
+ { url = "https://files.pythonhosted.org/packages/4d/d2/64be2e429eb4fca7f7e1c52a91b12663aeaf25de3895e5cca0f47ef2a8d0/kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c", size = 64998 },
+ { url = "https://files.pythonhosted.org/packages/b0/69/ce68dd0c85755ae2de490bf015b62f2cea5f6b14ff00a463f9d0774449ff/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1", size = 125700 },
+ { url = "https://files.pythonhosted.org/packages/74/aa/937aac021cf9d4349990d47eb319309a51355ed1dbdc9c077cdc9224cb11/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e", size = 67537 },
+ { url = "https://files.pythonhosted.org/packages/ee/20/3a87fbece2c40ad0f6f0aefa93542559159c5f99831d596050e8afae7a9f/kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7", size = 65514 },
+ { url = "https://files.pythonhosted.org/packages/f0/7f/f943879cda9007c45e1f7dba216d705c3a18d6b35830e488b6c6a4e7cdf0/kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c", size = 1584848 },
+ { url = "https://files.pythonhosted.org/packages/37/f8/4d4f85cc1870c127c88d950913370dd76138482161cd07eabbc450deff01/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368", size = 1391542 },
+ { url = "https://files.pythonhosted.org/packages/04/0b/65dd2916c84d252b244bd405303220f729e7c17c9d7d33dca6feeff9ffc4/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489", size = 1404447 },
+ { url = "https://files.pythonhosted.org/packages/39/5c/2606a373247babce9b1d056c03a04b65f3cf5290a8eac5d7bdead0a17e21/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1", size = 1455918 },
+ { url = "https://files.pythonhosted.org/packages/d5/d1/c6078b5756670658e9192a2ef11e939c92918833d2745f85cd14a6004bdf/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3", size = 1072856 },
+ { url = "https://files.pythonhosted.org/packages/cb/c8/7def6ddf16eb2b3741d8b172bdaa9af882b03c78e9b0772975408801fa63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18", size = 2333580 },
+ { url = "https://files.pythonhosted.org/packages/9e/87/2ac1fce0eb1e616fcd3c35caa23e665e9b1948bb984f4764790924594128/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021", size = 2423018 },
+ { url = "https://files.pythonhosted.org/packages/67/13/c6700ccc6cc218716bfcda4935e4b2997039869b4ad8a94f364c5a3b8e63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310", size = 2062804 },
+ { url = "https://files.pythonhosted.org/packages/1b/bd/877056304626943ff0f1f44c08f584300c199b887cb3176cd7e34f1515f1/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3", size = 2597482 },
+ { url = "https://files.pythonhosted.org/packages/75/19/c60626c47bf0f8ac5dcf72c6c98e266d714f2fbbfd50cf6dab5ede3aaa50/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2", size = 2394328 },
+ { url = "https://files.pythonhosted.org/packages/47/84/6a6d5e5bb8273756c27b7d810d47f7ef2f1f9b9fd23c9ee9a3f8c75c9cef/kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53", size = 68410 },
+ { url = "https://files.pythonhosted.org/packages/e4/d7/060f45052f2a01ad5762c8fdecd6d7a752b43400dc29ff75cd47225a40fd/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615", size = 123231 },
+ { url = "https://files.pythonhosted.org/packages/c2/a7/78da680eadd06ff35edef6ef68a1ad273bad3e2a0936c9a885103230aece/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02", size = 66489 },
+ { url = "https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e", size = 64063 },
+ { url = "https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac", size = 1475913 },
+ { url = "https://files.pythonhosted.org/packages/6b/f0/f768ae564a710135630672981231320bc403cf9152b5596ec5289de0f106/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05", size = 1282782 },
+ { url = "https://files.pythonhosted.org/packages/e2/9f/1de7aad00697325f05238a5f2eafbd487fb637cc27a558b5367a5f37fb7f/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd", size = 1300815 },
+ { url = "https://files.pythonhosted.org/packages/5a/c2/297f25141d2e468e0ce7f7a7b92e0cf8918143a0cbd3422c1ad627e85a06/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a", size = 1347925 },
+ { url = "https://files.pythonhosted.org/packages/b9/d3/f4c73a02eb41520c47610207b21afa8cdd18fdbf64ffd94674ae21c4812d/kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554", size = 991322 },
+ { url = "https://files.pythonhosted.org/packages/7b/46/d3f2efef7732fcda98d22bf4ad5d3d71d545167a852ca710a494f4c15343/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581", size = 2232857 },
+ { url = "https://files.pythonhosted.org/packages/3f/ec/2d9756bf2b6d26ae4349b8d3662fb3993f16d80c1f971c179ce862b9dbae/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303", size = 2329376 },
+ { url = "https://files.pythonhosted.org/packages/8f/9f/876a0a0f2260f1bde92e002b3019a5fabc35e0939c7d945e0fa66185eb20/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9", size = 1982549 },
+ { url = "https://files.pythonhosted.org/packages/6c/4f/ba3624dfac23a64d54ac4179832860cb537c1b0af06024936e82ca4154a0/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79", size = 2494680 },
+ { url = "https://files.pythonhosted.org/packages/39/b7/97716b190ab98911b20d10bf92eca469121ec483b8ce0edd314f51bc85af/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796", size = 2297905 },
+ { url = "https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e", size = 75086 },
+ { url = "https://files.pythonhosted.org/packages/70/15/9b90f7df0e31a003c71649cf66ef61c3c1b862f48c81007fa2383c8bd8d7/kiwisolver-1.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df", size = 66577 },
+ { url = "https://files.pythonhosted.org/packages/17/01/7dc8c5443ff42b38e72731643ed7cf1ed9bf01691ae5cdca98501999ed83/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e", size = 125794 },
+ { url = "https://files.pythonhosted.org/packages/46/8a/b4ebe46ebaac6a303417fab10c2e165c557ddaff558f9699d302b256bc53/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4", size = 67646 },
+ { url = "https://files.pythonhosted.org/packages/60/35/10a844afc5f19d6f567359bf4789e26661755a2f36200d5d1ed8ad0126e5/kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028", size = 65511 },
+ { url = "https://files.pythonhosted.org/packages/f8/8a/685b297052dd041dcebce8e8787b58923b6e78acc6115a0dc9189011c44b/kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657", size = 1584858 },
+ { url = "https://files.pythonhosted.org/packages/9e/80/04865e3d4638ac5bddec28908916df4a3075b8c6cc101786a96803188b96/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920", size = 1392539 },
+ { url = "https://files.pythonhosted.org/packages/ba/01/77a19cacc0893fa13fafa46d1bba06fb4dc2360b3292baf4b56d8e067b24/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9", size = 1405310 },
+ { url = "https://files.pythonhosted.org/packages/53/39/bcaf5d0cca50e604cfa9b4e3ae1d64b50ca1ae5b754122396084599ef903/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d", size = 1456244 },
+ { url = "https://files.pythonhosted.org/packages/d0/7a/72c187abc6975f6978c3e39b7cf67aeb8b3c0a8f9790aa7fd412855e9e1f/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65", size = 1073154 },
+ { url = "https://files.pythonhosted.org/packages/c7/ca/cf5b25783ebbd59143b4371ed0c8428a278abe68d6d0104b01865b1bbd0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa", size = 2334377 },
+ { url = "https://files.pythonhosted.org/packages/4a/e5/b1f492adc516796e88751282276745340e2a72dcd0d36cf7173e0daf3210/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0", size = 2425288 },
+ { url = "https://files.pythonhosted.org/packages/e6/e5/9b21fbe91a61b8f409d74a26498706e97a48008bfcd1864373d32a6ba31c/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9", size = 2063158 },
+ { url = "https://files.pythonhosted.org/packages/b1/02/83f47986138310f95ea95531f851b2a62227c11cbc3e690ae1374fe49f0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f", size = 2597260 },
+ { url = "https://files.pythonhosted.org/packages/07/18/43a5f24608d8c313dd189cf838c8e68d75b115567c6279de7796197cfb6a/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646", size = 2394403 },
+ { url = "https://files.pythonhosted.org/packages/3b/b5/98222136d839b8afabcaa943b09bd05888c2d36355b7e448550211d1fca4/kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681", size = 79687 },
+ { url = "https://files.pythonhosted.org/packages/99/a2/ca7dc962848040befed12732dff6acae7fb3c4f6fc4272b3f6c9a30b8713/kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57", size = 70032 },
+ { url = "https://files.pythonhosted.org/packages/e9/eb/5fcbbbf9a0e2c3a35effb88831a483345326bbc3a030a3b5b69aee647f84/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232", size = 59532 },
+ { url = "https://files.pythonhosted.org/packages/c3/9b/e17104555bb4db148fd52327feea1e96be4b88e8e008b029002c281a21ab/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a", size = 57420 },
+ { url = "https://files.pythonhosted.org/packages/48/44/2b5b95b7aa39fb2d8d9d956e0f3d5d45aef2ae1d942d4c3ffac2f9cfed1a/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737", size = 79892 },
+ { url = "https://files.pythonhosted.org/packages/52/7d/7157f9bba6b455cfb4632ed411e199fc8b8977642c2b12082e1bd9e6d173/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16", size = 77603 },
+ { url = "https://files.pythonhosted.org/packages/0a/dd/8050c947d435c8d4bc94e3252f4d8bb8a76cfb424f043a8680be637a57f1/kiwisolver-1.5.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:59cd8683f575d96df5bb48f6add94afc055012c29e28124fcae2b63661b9efb1", size = 73558 },
+]
+
+[[package]]
+name = "lark"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151 },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "3.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
+]
+
+[[package]]
+name = "markupsafe"
+version = "3.0.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631 },
+ { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058 },
+ { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287 },
+ { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940 },
+ { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887 },
+ { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692 },
+ { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471 },
+ { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923 },
+ { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572 },
+ { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077 },
+ { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876 },
+ { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615 },
+ { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020 },
+ { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332 },
+ { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947 },
+ { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962 },
+ { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760 },
+ { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529 },
+ { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015 },
+ { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540 },
+ { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105 },
+ { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906 },
+ { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622 },
+ { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029 },
+ { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374 },
+ { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980 },
+ { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990 },
+ { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784 },
+ { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588 },
+ { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041 },
+ { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543 },
+ { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113 },
+ { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911 },
+ { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658 },
+ { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066 },
+ { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639 },
+ { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569 },
+ { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284 },
+ { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801 },
+ { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769 },
+ { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642 },
+ { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612 },
+ { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200 },
+ { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973 },
+ { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619 },
+ { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029 },
+ { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408 },
+ { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005 },
+ { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048 },
+ { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821 },
+ { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606 },
+ { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043 },
+ { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747 },
+ { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341 },
+ { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073 },
+ { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661 },
+ { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069 },
+ { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670 },
+ { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598 },
+ { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261 },
+ { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835 },
+ { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733 },
+ { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672 },
+ { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819 },
+ { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426 },
+ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146 },
+]
+
+[[package]]
+name = "matplotlib"
+version = "3.10.9"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "contourpy" },
+ { name = "cycler" },
+ { name = "fonttools" },
+ { name = "kiwisolver" },
+ { name = "numpy" },
+ { name = "packaging" },
+ { name = "pillow" },
+ { name = "pyparsing" },
+ { name = "python-dateutil" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/63/1b/4be5be87d43d327a0cf4de1a56e86f7f84c89312452406cf122efe2839e6/matplotlib-3.10.9.tar.gz", hash = "sha256:fd66508e8c6877d98e586654b608a0456db8d7e8a546eb1e2600efd957302358", size = 34811233 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4c/8c/290f021104741fea63769c31494f5324c0cd249bf536a65a4350767b1f22/matplotlib-3.10.9-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:68cfdcede415f7c8f5577b03303dd94526cdb6d11036cecdc205e08733b2d2bb", size = 8306860 },
+ { url = "https://files.pythonhosted.org/packages/51/18/325cd32ece1120d1da51cc4e4294c6580190699490183fc2fe8cb6d61ec5/matplotlib-3.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfca0129678bd56379db26c52b5d77ed7de314c047492fbdc763aa7501710cfb", size = 8199254 },
+ { url = "https://files.pythonhosted.org/packages/79/db/e28c1b83e3680740aa78925f5fb2ae4d16207207419ad75ea9fe604f8676/matplotlib-3.10.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e436d155fa8a3399dc62683f8f5d0e2e50d25d0144a73edd73f82eec8f4abfb", size = 8777092 },
+ { url = "https://files.pythonhosted.org/packages/55/fa/3ce7adfe9ba101748f465211660d9c6374c876b671bdb8c2bb6d347e8b94/matplotlib-3.10.9-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56fc0bd271b00025c6edfdc7c2dcd247372c8e1544971d62e1dc7c17367e8bf9", size = 9595691 },
+ { url = "https://files.pythonhosted.org/packages/36/c4/6960a76686ed668f2c60f84e9799ba4c0d56abdb36b1577b60c1d061d1ec/matplotlib-3.10.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5a6104ed666402ba5106d7f36e0e0cdca4e8d7fa4d39708ca88019e2835a2eb", size = 9659771 },
+ { url = "https://files.pythonhosted.org/packages/7e/0d/271aace3342157c64700c9ff4c59c7b392f3dbab393692e8db6fbe7ab96c/matplotlib-3.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:d730e984eddf56974c3e72b6129c7ca462ac38dc624338f4b0b23eb23ecba00f", size = 8205112 },
+ { url = "https://files.pythonhosted.org/packages/e2/ee/cb57ad4754f3e7b9174ce6ce66d9205fb827067e48a9f58ac09d7e7d6b77/matplotlib-3.10.9-cp311-cp311-win_arm64.whl", hash = "sha256:51bf0ddbdc598e060d46c16b5590708f81a1624cefbaaf62f6a81bf9285b8c80", size = 8132310 },
+ { url = "https://files.pythonhosted.org/packages/35/c6/5581e26c72233ebb2a2a6fed2d24fb7c66b4700120b813f51b0555acf0b6/matplotlib-3.10.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f0c3c28d9fbcc1fe7a03be236d73430cf6409c41fb2383a7ac52fe932b072cb1", size = 8319908 },
+ { url = "https://files.pythonhosted.org/packages/b7/18/4880dd762e40cd360c1bf06e890c5a97b997e91cb324602b1a19950ad5ce/matplotlib-3.10.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41cb28c2bd769aa3e98322c6ab09854cbcc52ab69d2759d681bba3e327b2b320", size = 8216016 },
+ { url = "https://files.pythonhosted.org/packages/32/91/d024616abdba99e83120e07a20658976f6a343646710760c4a51df126029/matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ae20801130378b82d647ff5047c07316295b68dc054ca6b3c13519d0ea624285", size = 8789336 },
+ { url = "https://files.pythonhosted.org/packages/5c/04/030a2f61ef2158f5e4c259487a92ac877732499fb33d871585d89e03c42d/matplotlib-3.10.9-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c63ebcd8b4b169eb2f5c200552ae6b8be8999a005b6b507ed76fb8d7d674fe2", size = 9604602 },
+ { url = "https://files.pythonhosted.org/packages/fc/c2/541e4d09d87bb6b5830fc28b4c887a9a8cf4e1c6cee698a8c05552ae2003/matplotlib-3.10.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d75d11c949914165976c621b2324f9ef162af7ebf4b057ddf95dd1dba7e5edcf", size = 9670966 },
+ { url = "https://files.pythonhosted.org/packages/04/a1/4571fc46e7702de8d0c2dc54ad1b2f8e29328dea3ee90831181f7353d93c/matplotlib-3.10.9-cp312-cp312-win_amd64.whl", hash = "sha256:d091f9d758b34aaaaa6331d13574bf01891d903b3dec59bfff458ef7551de5d6", size = 8217462 },
+ { url = "https://files.pythonhosted.org/packages/4b/d0/2269edb12aa30c13c8bcc9382892e39943ce1d28aab4ec296e0381798e81/matplotlib-3.10.9-cp312-cp312-win_arm64.whl", hash = "sha256:10cc5ce06d10231c36f40e875f3c7e8050362a4ee8f0ee5d29a6b3277d57bb42", size = 8136688 },
+ { url = "https://files.pythonhosted.org/packages/aa/d3/8d4f6afbecb49fc04e060a57c0fce39ea51cc163a6bd87303ccd698e4fa6/matplotlib-3.10.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b580440f1ff81a0e34122051a3dfabb7e4b7f9e380629929bde0eff9af72165f", size = 8320331 },
+ { url = "https://files.pythonhosted.org/packages/63/d9/9e14bc7564bf92d5ffa801ae5fac819ce74b925dfb55e3ebde61a3bbad3e/matplotlib-3.10.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b1b745c489cd1a77a0dc1120a05dc87af9798faebc913601feb8c73d89bf2d1e", size = 8216461 },
+ { url = "https://files.pythonhosted.org/packages/8a/17/4402d0d14ccf1dfc70932600b68097fbbf9c898a4871d2cbbe79c7801a32/matplotlib-3.10.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8f3bcac1ca5ed000a6f4337d47ba67dfddf37ed6a46c15fd7f014997f7bf865f", size = 8790091 },
+ { url = "https://files.pythonhosted.org/packages/3e/0b/322aeec06dd9b91411f92028b37d447342770a24392aa4813e317064dad5/matplotlib-3.10.9-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a8d66a55def891c33147ba3ba9bfcabf0b526a43764c818acbb4525e5ed0838", size = 9605027 },
+ { url = "https://files.pythonhosted.org/packages/74/88/5f13482f55e7b00bcfc09838b093c2456e1379978d2a146844aae05350ad/matplotlib-3.10.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d843374407c4017a6403b59c6c81606773d136f3259d5b6da3131bc814542cc2", size = 9671269 },
+ { url = "https://files.pythonhosted.org/packages/c5/e0/0840fd2f93da988ec660b8ad1984abe9f25d2aed22a5e394ff1c68c88307/matplotlib-3.10.9-cp313-cp313-win_amd64.whl", hash = "sha256:f4399f64b3e94cd500195490972ae1ee81170df1636fa15364d157d5bdd7b921", size = 8217588 },
+ { url = "https://files.pythonhosted.org/packages/47/b9/d706d06dd605c49b9f83a2aed8c13e3e5db70697d7a80b7e3d7915de6b17/matplotlib-3.10.9-cp313-cp313-win_arm64.whl", hash = "sha256:ba7b3b8ef09eab7df0e86e9ae086faa433efbfbdb46afcb3aa16aabf779469a8", size = 8136913 },
+ { url = "https://files.pythonhosted.org/packages/9b/45/6e32d96978264c8ca8c4b1010adb955a1a49cfaf314e212bbc8908f04a61/matplotlib-3.10.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:09218df8a93712bd6ea133e83a153c755448cf7868316c531cffcc43f69d1cc9", size = 8368019 },
+ { url = "https://files.pythonhosted.org/packages/86/0a/c8e3d3bba245f0f7fc424937f8ff7ef77291a36af3edb97ccd78aa93d84f/matplotlib-3.10.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:82368699727bfb7b0182e1aa13082e3c08e092fa1a25d3e1fd92405bff96f6d4", size = 8264645 },
+ { url = "https://files.pythonhosted.org/packages/3d/aa/5bf5a14fe4fed73a4209a155606f8096ff797aad89c6c35179026571133e/matplotlib-3.10.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3225f4e1edcb8c86c884ddf79ebe20ecd0a67d30188f279897554ccd8fded4dc", size = 8802194 },
+ { url = "https://files.pythonhosted.org/packages/dd/5e/b4be852d6bba6fd15893fadf91ff26ae49cb91aac789e95dde9d342e664f/matplotlib-3.10.9-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de2445a0c6690d21b7eb6ce071cebad6d40a2e9bdf10d039074a96ba19797b99", size = 9622684 },
+ { url = "https://files.pythonhosted.org/packages/4c/3d/ed428c971139112ef730f62770654d609467346d09d4b62617e1afd68a5a/matplotlib-3.10.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b2b9516251cb89ff618d757daec0e2ed1bf21248013844a853d87ef85ab3081d", size = 9680790 },
+ { url = "https://files.pythonhosted.org/packages/e7/09/052e884aaf2b985c63cb79f715f1d5b6a3eaa7de78f6a52b9dbc077d5b53/matplotlib-3.10.9-cp313-cp313t-win_amd64.whl", hash = "sha256:e9fae004b941b23ff2edcf1567a857ed77bafc8086ffa258190462328434faf8", size = 8287571 },
+ { url = "https://files.pythonhosted.org/packages/f4/38/ae27288e788c35a4250491422f3db7750366fc8c97d6f36fbdecfc1f5518/matplotlib-3.10.9-cp313-cp313t-win_arm64.whl", hash = "sha256:6b63d9c7c769b88ab81e10dc86e4e0607cf56817b9f9e6cf24b2a5f1693b8e38", size = 8188292 },
+ { url = "https://files.pythonhosted.org/packages/d6/e6/3bd8afd04949f02eabc1c17115ea5255e19cacd4d06fc5abdde4eeb0052c/matplotlib-3.10.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:172db52c9e683f5d12eaf57f0f54834190e12581fe1cc2a19595a8f5acb4e77d", size = 8321276 },
+ { url = "https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97e35e8d39ccc85859095e01a53847432ba9a53ddf7986f7a54a11b73d0e143f", size = 8218218 },
+ { url = "https://files.pythonhosted.org/packages/85/8f/becc9722cafc64f5d2eb0b7c1bf5f585271c618a45dbd8fabeb021f898b6/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aba1615dabe83188e19d4f75a253c6a08423e04c1425e64039f800050a69de6b", size = 9608145 },
+ { url = "https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34cf8167e023ad956c15f36302911d5406bd99a9862c1a8499ea6f7c0e015dc2", size = 9885085 },
+ { url = "https://files.pythonhosted.org/packages/a5/fd/fa69f2221534e80cc5772ac2b7d222011a2acafc2ec7216d5dd174c864ae/matplotlib-3.10.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59476c6d29d612b8e9bb6ce8c5b631be6ba8f9e3a2421f22a02b192c7dd28716", size = 9672358 },
+ { url = "https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl", hash = "sha256:336b9acc64d309063126edcdaca00db9373af3c476bb94388fe9c5a53ad13e6f", size = 8349970 },
+ { url = "https://files.pythonhosted.org/packages/64/dc/95d60ecaefe30680a154b52ea96ab4b0dab547f1fd6aa12f5fb655e89cae/matplotlib-3.10.9-cp314-cp314-win_arm64.whl", hash = "sha256:2dc9477819ffd78ad12a20df1d9d6a6bd4fec6aaa9072681465fddca052f1456", size = 8272785 },
+ { url = "https://files.pythonhosted.org/packages/70/a0/005d68bc8b8418300ce6591f18586910a8526806e2ab663933d9f20a41e9/matplotlib-3.10.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:da4e09638420548f31c354032a6250e473c68e5a4e96899b4844cf39ddea23fe", size = 8367999 },
+ { url = "https://files.pythonhosted.org/packages/22/05/1236cc9290be70b2498af20ca348add76e3fffe7f67b477db5133a84f3ea/matplotlib-3.10.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:345f6f68ecc8da0ca56fad2ea08fde1a115eda530079eca185d50a7bc3e146c6", size = 8264543 },
+ { url = "https://files.pythonhosted.org/packages/cd/c2/071f5a5ff6c5bd63aaaf2f45c811d9bf2ced94bde188d9e1a519e21d0cba/matplotlib-3.10.9-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4edcfbd8565339aa62f1cd4012f7180926fdbe71850f7b0d3c379c175cd6b66c", size = 9622800 },
+ { url = "https://files.pythonhosted.org/packages/95/57/da7d1f10a85624b9e7db68e069dd94e58dc41dbf9463c5921632ecbe3661/matplotlib-3.10.9-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6be157fe17fc37cb95ac1d7374cf717ce9259616edec911a78d9d26dae8522d4", size = 9888561 },
+ { url = "https://files.pythonhosted.org/packages/67/b2/ef8d6bb59b0edb6c16c968b70f548aa13b54348972def5aa6ac85df67145/matplotlib-3.10.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4e42042d54db34fda4e95a7bd3e5789c2a995d2dad3eb8850232ee534092fbbf", size = 9680884 },
+ { url = "https://files.pythonhosted.org/packages/61/1c/d21bfeb9931881ebe96bcfcff27c7ae4b160ae0ec291a714c42641a56d75/matplotlib-3.10.9-cp314-cp314t-win_amd64.whl", hash = "sha256:c27df8b3848f32a83d1767566595e43cfaa4460380974da06f4279a7ec143c39", size = 8432333 },
+ { url = "https://files.pythonhosted.org/packages/78/23/92493c3e6e1b635ccfff146f7b99e674808787915420373ac399283764c2/matplotlib-3.10.9-cp314-cp314t-win_arm64.whl", hash = "sha256:a49f1eadc84ca85fd72fa4e89e70e61bf86452df6f971af04b12c60761a0772c", size = 8324785 },
+ { url = "https://files.pythonhosted.org/packages/63/e2/9f66ca6a651a52abfe0d4964ce01439ed34f3f1e119de10ff3a07f403043/matplotlib-3.10.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:42fb814efabe95c06c1994d8ab5a8385f43a249e23badd3ba931d4308e5bca20", size = 8304420 },
+ { url = "https://files.pythonhosted.org/packages/e8/e8/467c03568218792906aa87b5e7bb379b605e056ed0c74fe00c051786d925/matplotlib-3.10.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f76e640a5268850bfda54b5131b1b1941cc685e42c5fa98ed9f2d64038308cba", size = 8197981 },
+ { url = "https://files.pythonhosted.org/packages/6f/87/afead29192170917537934c6aff4b008c805fff7b1ccea0c79120d96beda/matplotlib-3.10.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3fc0364dfbe1d07f6d15c5ebd0c5bf89e126916e5a8667dd4a7a6e84c36653d4", size = 8774002 },
+]
+
+[[package]]
+name = "matplotlib-inline"
+version = "0.2.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516 },
+]
+
+[[package]]
+name = "mdit-py-plugins"
+version = "0.5.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b2/fd/a756d36c0bfba5f6e39a1cdbdbfdd448dc02692467d83816dff4592a1ebc/mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6", size = 44655 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f", size = 57205 },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
+]
+
+[[package]]
+name = "mistune"
+version = "3.2.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598 },
+]
+
+[[package]]
+name = "myst-parser"
+version = "4.0.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "docutils" },
+ { name = "jinja2" },
+ { name = "markdown-it-py" },
+ { name = "mdit-py-plugins" },
+ { name = "pyyaml" },
+ { name = "sphinx" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/a5/9626ba4f73555b3735ad86247a8077d4603aa8628537687c839ab08bfe44/myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4", size = 93985 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579 },
+]
+
+[[package]]
+name = "nbclient"
+version = "0.10.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jupyter-client" },
+ { name = "jupyter-core" },
+ { name = "nbformat" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465 },
+]
+
+[[package]]
+name = "nbconvert"
+version = "7.17.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "beautifulsoup4" },
+ { name = "bleach", extra = ["css"] },
+ { name = "defusedxml" },
+ { name = "jinja2" },
+ { name = "jupyter-core" },
+ { name = "jupyterlab-pygments" },
+ { name = "markupsafe" },
+ { name = "mistune" },
+ { name = "nbclient" },
+ { name = "nbformat" },
+ { name = "packaging" },
+ { name = "pandocfilters" },
+ { name = "pygments" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/01/b1/708e53fe2e429c103c6e6e159106bcf0357ac41aa4c28772bd8402339051/nbconvert-7.17.1.tar.gz", hash = "sha256:34d0d0a7e73ce3cbab6c5aae8f4f468797280b01fd8bd2ca746da8569eddd7d2", size = 865311 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/67/f8/bb0a9d5f46819c821dc1f004aa2cc29b1d91453297dbf5ff20470f00f193/nbconvert-7.17.1-py3-none-any.whl", hash = "sha256:aa85c087b435e7bf1ffd03319f658e285f2b89eccab33bc1ba7025495ab3e7c8", size = 261927 },
+]
+
+[[package]]
+name = "nbformat"
+version = "5.10.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "fastjsonschema" },
+ { name = "jsonschema" },
+ { name = "jupyter-core" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454 },
+]
+
+[[package]]
+name = "nest-asyncio"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195 },
+]
+
+[[package]]
+name = "nodeenv"
+version = "1.10.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438 },
+]
+
+[[package]]
+name = "notebook"
+version = "7.5.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jupyter-server" },
+ { name = "jupyterlab" },
+ { name = "jupyterlab-server" },
+ { name = "notebook-shim" },
+ { name = "tornado" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/1f/6d/41052c48d6f6349ca0a7c4d1f6a78464de135e6d18f5829ba2510e62184c/notebook-7.5.5.tar.gz", hash = "sha256:dc0bfab0f2372c8278c457423d3256c34154ac2cc76bf20e9925260c461013c3", size = 14169167 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f8/aa/cbd1deb9f07446241e88f8d5fecccd95b249bca0b4e5482214a4d1714c49/notebook-7.5.5-py3-none-any.whl", hash = "sha256:a7c14dbeefa6592e87f72290ca982e0c10f5bbf3786be2a600fda9da2764a2b8", size = 14578929 },
+]
+
+[[package]]
+name = "notebook-shim"
+version = "0.2.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jupyter-server" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307 },
+]
+
+[[package]]
+name = "numpy"
+version = "2.4.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/9f/b8cef5bffa569759033adda9481211426f12f53299629b410340795c2514/numpy-2.4.4.tar.gz", hash = "sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0", size = 20731587 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ef/c6/4218570d8c8ecc9704b5157a3348e486e84ef4be0ed3e38218ab473c83d2/numpy-2.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db", size = 16976799 },
+ { url = "https://files.pythonhosted.org/packages/dd/92/b4d922c4a5f5dab9ed44e6153908a5c665b71acf183a83b93b690996e39b/numpy-2.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0", size = 14971552 },
+ { url = "https://files.pythonhosted.org/packages/8a/dc/df98c095978fa6ee7b9a9387d1d58cbb3d232d0e69ad169a4ce784bde4fd/numpy-2.4.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015", size = 5476566 },
+ { url = "https://files.pythonhosted.org/packages/28/34/b3fdcec6e725409223dd27356bdf5a3c2cc2282e428218ecc9cb7acc9763/numpy-2.4.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40", size = 6806482 },
+ { url = "https://files.pythonhosted.org/packages/68/62/63417c13aa35d57bee1337c67446761dc25ea6543130cf868eace6e8157b/numpy-2.4.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d", size = 15973376 },
+ { url = "https://files.pythonhosted.org/packages/cf/c5/9fcb7e0e69cef59cf10c746b84f7d58b08bc66a6b7d459783c5a4f6101a6/numpy-2.4.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502", size = 16925137 },
+ { url = "https://files.pythonhosted.org/packages/7e/43/80020edacb3f84b9efdd1591120a4296462c23fd8db0dde1666f6ef66f13/numpy-2.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd", size = 17329414 },
+ { url = "https://files.pythonhosted.org/packages/fd/06/af0658593b18a5f73532d377188b964f239eb0894e664a6c12f484472f97/numpy-2.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5", size = 18658397 },
+ { url = "https://files.pythonhosted.org/packages/e6/ce/13a09ed65f5d0ce5c7dd0669250374c6e379910f97af2c08c57b0608eee4/numpy-2.4.4-cp311-cp311-win32.whl", hash = "sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e", size = 6239499 },
+ { url = "https://files.pythonhosted.org/packages/bd/63/05d193dbb4b5eec1eca73822d80da98b511f8328ad4ae3ca4caf0f4db91d/numpy-2.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e", size = 12614257 },
+ { url = "https://files.pythonhosted.org/packages/87/c5/8168052f080c26fa984c413305012be54741c9d0d74abd7fbeeccae3889f/numpy-2.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e", size = 10486775 },
+ { url = "https://files.pythonhosted.org/packages/28/05/32396bec30fb2263770ee910142f49c1476d08e8ad41abf8403806b520ce/numpy-2.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b", size = 16689272 },
+ { url = "https://files.pythonhosted.org/packages/c5/f3/a983d28637bfcd763a9c7aafdb6d5c0ebf3d487d1e1459ffdb57e2f01117/numpy-2.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e", size = 14699573 },
+ { url = "https://files.pythonhosted.org/packages/9b/fd/e5ecca1e78c05106d98028114f5c00d3eddb41207686b2b7de3e477b0e22/numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842", size = 5204782 },
+ { url = "https://files.pythonhosted.org/packages/de/2f/702a4594413c1a8632092beae8aba00f1d67947389369b3777aed783fdca/numpy-2.4.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8", size = 6552038 },
+ { url = "https://files.pythonhosted.org/packages/7f/37/eed308a8f56cba4d1fdf467a4fc67ef4ff4bf1c888f5fc980481890104b1/numpy-2.4.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121", size = 15670666 },
+ { url = "https://files.pythonhosted.org/packages/0a/0d/0e3ecece05b7a7e87ab9fb587855548da437a061326fff64a223b6dcb78a/numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e", size = 16645480 },
+ { url = "https://files.pythonhosted.org/packages/34/49/f2312c154b82a286758ee2f1743336d50651f8b5195db18cdb63675ff649/numpy-2.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44", size = 17020036 },
+ { url = "https://files.pythonhosted.org/packages/7b/e9/736d17bd77f1b0ec4f9901aaec129c00d59f5d84d5e79bba540ef12c2330/numpy-2.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d", size = 18368643 },
+ { url = "https://files.pythonhosted.org/packages/63/f6/d417977c5f519b17c8a5c3bc9e8304b0908b0e21136fe43bf628a1343914/numpy-2.4.4-cp312-cp312-win32.whl", hash = "sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827", size = 5961117 },
+ { url = "https://files.pythonhosted.org/packages/2d/5b/e1deebf88ff431b01b7406ca3583ab2bbb90972bbe1c568732e49c844f7e/numpy-2.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a", size = 12320584 },
+ { url = "https://files.pythonhosted.org/packages/58/89/e4e856ac82a68c3ed64486a544977d0e7bdd18b8da75b78a577ca31c4395/numpy-2.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec", size = 10221450 },
+ { url = "https://files.pythonhosted.org/packages/14/1d/d0a583ce4fefcc3308806a749a536c201ed6b5ad6e1322e227ee4848979d/numpy-2.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50", size = 16684933 },
+ { url = "https://files.pythonhosted.org/packages/c1/62/2b7a48fbb745d344742c0277f01286dead15f3f68e4f359fbfcf7b48f70f/numpy-2.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115", size = 14694532 },
+ { url = "https://files.pythonhosted.org/packages/e5/87/499737bfba066b4a3bebff24a8f1c5b2dee410b209bc6668c9be692580f0/numpy-2.4.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af", size = 5199661 },
+ { url = "https://files.pythonhosted.org/packages/cd/da/464d551604320d1491bc345efed99b4b7034143a85787aab78d5691d5a0e/numpy-2.4.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c", size = 6547539 },
+ { url = "https://files.pythonhosted.org/packages/7d/90/8d23e3b0dafd024bf31bdec225b3bb5c2dbfa6912f8a53b8659f21216cbf/numpy-2.4.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103", size = 15668806 },
+ { url = "https://files.pythonhosted.org/packages/d1/73/a9d864e42a01896bb5974475438f16086be9ba1f0d19d0bb7a07427c4a8b/numpy-2.4.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83", size = 16632682 },
+ { url = "https://files.pythonhosted.org/packages/34/fb/14570d65c3bde4e202a031210475ae9cde9b7686a2e7dc97ee67d2833b35/numpy-2.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed", size = 17019810 },
+ { url = "https://files.pythonhosted.org/packages/8a/77/2ba9d87081fd41f6d640c83f26fb7351e536b7ce6dd9061b6af5904e8e46/numpy-2.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959", size = 18357394 },
+ { url = "https://files.pythonhosted.org/packages/a2/23/52666c9a41708b0853fa3b1a12c90da38c507a3074883823126d4e9d5b30/numpy-2.4.4-cp313-cp313-win32.whl", hash = "sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed", size = 5959556 },
+ { url = "https://files.pythonhosted.org/packages/57/fb/48649b4971cde70d817cf97a2a2fdc0b4d8308569f1dd2f2611959d2e0cf/numpy-2.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf", size = 12317311 },
+ { url = "https://files.pythonhosted.org/packages/ba/d8/11490cddd564eb4de97b4579ef6bfe6a736cc07e94c1598590ae25415e01/numpy-2.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d", size = 10222060 },
+ { url = "https://files.pythonhosted.org/packages/99/5d/dab4339177a905aad3e2221c915b35202f1ec30d750dd2e5e9d9a72b804b/numpy-2.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5", size = 14822302 },
+ { url = "https://files.pythonhosted.org/packages/eb/e4/0564a65e7d3d97562ed6f9b0fd0fb0a6f559ee444092f105938b50043876/numpy-2.4.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7", size = 5327407 },
+ { url = "https://files.pythonhosted.org/packages/29/8d/35a3a6ce5ad371afa58b4700f1c820f8f279948cca32524e0a695b0ded83/numpy-2.4.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93", size = 6647631 },
+ { url = "https://files.pythonhosted.org/packages/f4/da/477731acbd5a58a946c736edfdabb2ac5b34c3d08d1ba1a7b437fa0884df/numpy-2.4.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e", size = 15727691 },
+ { url = "https://files.pythonhosted.org/packages/e6/db/338535d9b152beabeb511579598418ba0212ce77cf9718edd70262cc4370/numpy-2.4.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40", size = 16681241 },
+ { url = "https://files.pythonhosted.org/packages/e2/a9/ad248e8f58beb7a0219b413c9c7d8151c5d285f7f946c3e26695bdbbe2df/numpy-2.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e", size = 17085767 },
+ { url = "https://files.pythonhosted.org/packages/b5/1a/3b88ccd3694681356f70da841630e4725a7264d6a885c8d442a697e1146b/numpy-2.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392", size = 18403169 },
+ { url = "https://files.pythonhosted.org/packages/c2/c9/fcfd5d0639222c6eac7f304829b04892ef51c96a75d479214d77e3ce6e33/numpy-2.4.4-cp313-cp313t-win32.whl", hash = "sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008", size = 6083477 },
+ { url = "https://files.pythonhosted.org/packages/d5/e3/3938a61d1c538aaec8ed6fd6323f57b0c2d2d2219512434c5c878db76553/numpy-2.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8", size = 12457487 },
+ { url = "https://files.pythonhosted.org/packages/97/6a/7e345032cc60501721ef94e0e30b60f6b0bd601f9174ebd36389a2b86d40/numpy-2.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233", size = 10292002 },
+ { url = "https://files.pythonhosted.org/packages/6e/06/c54062f85f673dd5c04cbe2f14c3acb8c8b95e3384869bb8cc9bff8cb9df/numpy-2.4.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0", size = 16684353 },
+ { url = "https://files.pythonhosted.org/packages/4c/39/8a320264a84404c74cc7e79715de85d6130fa07a0898f67fb5cd5bd79908/numpy-2.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a", size = 14704914 },
+ { url = "https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a", size = 5210005 },
+ { url = "https://files.pythonhosted.org/packages/63/eb/fcc338595309910de6ecabfcef2419a9ce24399680bfb149421fa2df1280/numpy-2.4.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b", size = 6544974 },
+ { url = "https://files.pythonhosted.org/packages/44/5d/e7e9044032a716cdfaa3fba27a8e874bf1c5f1912a1ddd4ed071bf8a14a6/numpy-2.4.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a", size = 15684591 },
+ { url = "https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d", size = 16637700 },
+ { url = "https://files.pythonhosted.org/packages/b1/29/56d2bbef9465db24ef25393383d761a1af4f446a1df9b8cded4fe3a5a5d7/numpy-2.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252", size = 17035781 },
+ { url = "https://files.pythonhosted.org/packages/e3/2b/a35a6d7589d21f44cea7d0a98de5ddcbb3d421b2622a5c96b1edf18707c3/numpy-2.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f", size = 18362959 },
+ { url = "https://files.pythonhosted.org/packages/64/c9/d52ec581f2390e0f5f85cbfd80fb83d965fc15e9f0e1aec2195faa142cde/numpy-2.4.4-cp314-cp314-win32.whl", hash = "sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc", size = 6008768 },
+ { url = "https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74", size = 12449181 },
+ { url = "https://files.pythonhosted.org/packages/70/2e/14cda6f4d8e396c612d1bf97f22958e92148801d7e4f110cabebdc0eef4b/numpy-2.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb", size = 10496035 },
+ { url = "https://files.pythonhosted.org/packages/b1/e8/8fed8c8d848d7ecea092dc3469643f9d10bc3a134a815a3b033da1d2039b/numpy-2.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e", size = 14824958 },
+ { url = "https://files.pythonhosted.org/packages/05/1a/d8007a5138c179c2bf33ef44503e83d70434d2642877ee8fbb230e7c0548/numpy-2.4.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113", size = 5330020 },
+ { url = "https://files.pythonhosted.org/packages/99/64/ffb99ac6ae93faf117bcbd5c7ba48a7f45364a33e8e458545d3633615dda/numpy-2.4.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d", size = 6650758 },
+ { url = "https://files.pythonhosted.org/packages/6e/6e/795cc078b78a384052e73b2f6281ff7a700e9bf53bcce2ee579d4f6dd879/numpy-2.4.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d", size = 15729948 },
+ { url = "https://files.pythonhosted.org/packages/5f/86/2acbda8cc2af5f3d7bfc791192863b9e3e19674da7b5e533fded124d1299/numpy-2.4.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f", size = 16679325 },
+ { url = "https://files.pythonhosted.org/packages/bc/59/cafd83018f4aa55e0ac6fa92aa066c0a1877b77a615ceff1711c260ffae8/numpy-2.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0", size = 17084883 },
+ { url = "https://files.pythonhosted.org/packages/f0/85/a42548db84e65ece46ab2caea3d3f78b416a47af387fcbb47ec28e660dc2/numpy-2.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150", size = 18403474 },
+ { url = "https://files.pythonhosted.org/packages/ed/ad/483d9e262f4b831000062e5d8a45e342166ec8aaa1195264982bca267e62/numpy-2.4.4-cp314-cp314t-win32.whl", hash = "sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871", size = 6155500 },
+ { url = "https://files.pythonhosted.org/packages/c7/03/2fc4e14c7bd4ff2964b74ba90ecb8552540b6315f201df70f137faa5c589/numpy-2.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e", size = 12637755 },
+ { url = "https://files.pythonhosted.org/packages/58/78/548fb8e07b1a341746bfbecb32f2c268470f45fa028aacdbd10d9bc73aab/numpy-2.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7", size = 10566643 },
+ { url = "https://files.pythonhosted.org/packages/6b/33/8fae8f964a4f63ed528264ddf25d2b683d0b663e3cba26961eb838a7c1bd/numpy-2.4.4-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4", size = 16854491 },
+ { url = "https://files.pythonhosted.org/packages/bc/d0/1aabee441380b981cf8cdda3ae7a46aa827d1b5a8cce84d14598bc94d6d9/numpy-2.4.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e", size = 14895830 },
+ { url = "https://files.pythonhosted.org/packages/a5/b8/aafb0d1065416894fccf4df6b49ef22b8db045187949545bced89c034b8e/numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c", size = 5400927 },
+ { url = "https://files.pythonhosted.org/packages/d6/77/063baa20b08b431038c7f9ff5435540c7b7265c78cf56012a483019ca72d/numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3", size = 6715557 },
+ { url = "https://files.pythonhosted.org/packages/c7/a8/379542d45a14f149444c5c4c4e7714707239ce9cc1de8c2803958889da14/numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7", size = 15804253 },
+ { url = "https://files.pythonhosted.org/packages/a2/c8/f0a45426d6d21e7ea3310a15cf90c43a14d9232c31a837702dba437f3373/numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f", size = 16753552 },
+ { url = "https://files.pythonhosted.org/packages/04/74/f4c001f4714c3ad9ce037e18cf2b9c64871a84951eaa0baf683a9ca9301c/numpy-2.4.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119", size = 12509075 },
+]
+
+[[package]]
+name = "overrides"
+version = "7.7.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/36/86/b585f53236dec60aba864e050778b25045f857e17f6e5ea0ae95fe80edd2/overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a", size = 22812 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/ab/fc8290c6a4c722e5514d80f62b2dc4c4df1a68a41d1364e625c35990fcf3/overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49", size = 17832 },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195 },
+]
+
+[[package]]
+name = "pandocfilters"
+version = "1.5.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663 },
+]
+
+[[package]]
+name = "parso"
+version = "0.8.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/81/76/a1e769043c0c0c9fe391b702539d594731a4362334cdf4dc25d0c09761e7/parso-0.8.6.tar.gz", hash = "sha256:2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd", size = 401621 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b6/61/fae042894f4296ec49e3f193aff5d7c18440da9e48102c3315e1bc4519a7/parso-0.8.6-py2.py3-none-any.whl", hash = "sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff", size = 106894 },
+]
+
+[[package]]
+name = "pexpect"
+version = "4.9.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "ptyprocess" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772 },
+]
+
+[[package]]
+name = "pillow"
+version = "12.2.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab", size = 5354347 },
+ { url = "https://files.pythonhosted.org/packages/47/a1/d5ff69e747374c33a3b53b9f98cca7889fce1fd03d79cdc4e1bccc6c5a87/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65", size = 4695873 },
+ { url = "https://files.pythonhosted.org/packages/df/21/e3fbdf54408a973c7f7f89a23b2cb97a7ef30c61ab4142af31eee6aebc88/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7", size = 6280168 },
+ { url = "https://files.pythonhosted.org/packages/d3/f1/00b7278c7dd52b17ad4329153748f87b6756ec195ff786c2bdf12518337d/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e", size = 8088188 },
+ { url = "https://files.pythonhosted.org/packages/ad/cf/220a5994ef1b10e70e85748b75649d77d506499352be135a4989c957b701/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705", size = 6394401 },
+ { url = "https://files.pythonhosted.org/packages/e9/bd/e51a61b1054f09437acfbc2ff9106c30d1eb76bc1453d428399946781253/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176", size = 7079655 },
+ { url = "https://files.pythonhosted.org/packages/6b/3d/45132c57d5fb4b5744567c3817026480ac7fc3ce5d4c47902bc0e7f6f853/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b", size = 6503105 },
+ { url = "https://files.pythonhosted.org/packages/7d/2e/9df2fc1e82097b1df3dce58dc43286aa01068e918c07574711fcc53e6fb4/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909", size = 7203402 },
+ { url = "https://files.pythonhosted.org/packages/bd/2e/2941e42858ebb67e50ae741473de81c2984e6eff7b397017623c676e2e8d/pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808", size = 6378149 },
+ { url = "https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60", size = 7082626 },
+ { url = "https://files.pythonhosted.org/packages/c2/88/549194b5d6f1f494b485e493edc6693c0a16f4ada488e5bd974ed1f42fad/pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe", size = 2463531 },
+ { url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5", size = 5308279 },
+ { url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421", size = 4695490 },
+ { url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987", size = 6284462 },
+ { url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76", size = 8094744 },
+ { url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005", size = 6398371 },
+ { url = "https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780", size = 7087215 },
+ { url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5", size = 6509783 },
+ { url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5", size = 7212112 },
+ { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489 },
+ { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129 },
+ { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612 },
+ { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837 },
+ { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528 },
+ { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401 },
+ { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094 },
+ { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402 },
+ { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005 },
+ { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669 },
+ { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194 },
+ { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423 },
+ { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667 },
+ { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580 },
+ { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896 },
+ { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266 },
+ { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508 },
+ { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927 },
+ { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624 },
+ { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252 },
+ { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550 },
+ { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114 },
+ { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667 },
+ { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966 },
+ { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241 },
+ { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592 },
+ { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542 },
+ { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765 },
+ { url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848 },
+ { url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515 },
+ { url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159 },
+ { url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185 },
+ { url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386 },
+ { url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384 },
+ { url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599 },
+ { url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021 },
+ { url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360 },
+ { url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628 },
+ { url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321 },
+ { url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723 },
+ { url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400 },
+ { url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835 },
+ { url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225 },
+ { url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541 },
+ { url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251 },
+ { url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807 },
+ { url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935 },
+ { url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720 },
+ { url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498 },
+ { url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413 },
+ { url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084 },
+ { url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152 },
+ { url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579 },
+ { url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f", size = 5273969 },
+ { url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d", size = 4659674 },
+ { url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f", size = 5288479 },
+ { url = "https://files.pythonhosted.org/packages/49/62/5b0ed78fce87346be7a5cfcfaaad91f6a1f98c26f86bdbafa2066c647ef6/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e", size = 7032230 },
+ { url = "https://files.pythonhosted.org/packages/c3/28/ec0fc38107fc32536908034e990c47914c57cd7c5a3ece4d8d8f7ffd7e27/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0", size = 5355404 },
+ { url = "https://files.pythonhosted.org/packages/5e/8b/51b0eddcfa2180d60e41f06bd6d0a62202b20b59c68f5a132e615b75aecf/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1", size = 6002215 },
+ { url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e", size = 7080946 },
+]
+
+[[package]]
+name = "platformdirs"
+version = "4.9.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348 },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538 },
+]
+
+[[package]]
+name = "pre-commit"
+version = "4.6.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cfgv" },
+ { name = "identify" },
+ { name = "nodeenv" },
+ { name = "pyyaml" },
+ { name = "virtualenv" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/8e/22/2de9408ac81acbb8a7d05d4cc064a152ccf33b3d480ebe0cd292153db239/pre_commit-4.6.0.tar.gz", hash = "sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9", size = 198525 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b", size = 226472 },
+]
+
+[[package]]
+name = "prometheus-client"
+version = "0.25.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/1b/fb/d9aa83ffe43ce1f19e557c0971d04b90561b0cfd50762aafb01968285553/prometheus_client-0.25.0.tar.gz", hash = "sha256:5e373b75c31afb3c86f1a52fa1ad470c9aace18082d39ec0d2f918d11cc9ba28", size = 86035 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8d/9b/d4b1e644385499c8346fa9b622a3f030dce14cd6ef8a1871c221a17a67e7/prometheus_client-0.25.0-py3-none-any.whl", hash = "sha256:d5aec89e349a6ec230805d0df882f3807f74fd6c1a2fa86864e3c2279059fed1", size = 64154 },
+]
+
+[[package]]
+name = "prompt-toolkit"
+version = "3.0.52"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "wcwidth" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431 },
+]
+
+[[package]]
+name = "psutil"
+version = "7.2.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595 },
+ { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082 },
+ { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476 },
+ { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062 },
+ { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893 },
+ { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589 },
+ { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664 },
+ { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087 },
+ { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383 },
+ { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210 },
+ { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228 },
+ { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284 },
+ { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090 },
+ { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859 },
+ { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560 },
+ { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997 },
+ { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972 },
+ { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266 },
+ { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737 },
+ { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617 },
+]
+
+[[package]]
+name = "ptyprocess"
+version = "0.7.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993 },
+]
+
+[[package]]
+name = "pure-eval"
+version = "0.2.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842 },
+]
+
+[[package]]
+name = "pya"
+version = "0.5.2"
+source = { editable = "." }
+dependencies = [
+ { name = "matplotlib" },
+ { name = "pyamapping" },
+ { name = "scipy" },
+ { name = "soundfile" },
+]
+
+[package.optional-dependencies]
+example-notebooks = [
+ { name = "notebook" },
+]
+pyaudio = [
+ { name = "pyaudio" },
+]
+remote = [
+ { name = "ipywidgets" },
+ { name = "notebook" },
+ { name = "websocket" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "myst-parser" },
+ { name = "pre-commit" },
+ { name = "pydocstyle" },
+ { name = "pytest" },
+ { name = "pytest-cov" },
+ { name = "sphinx" },
+ { name = "sphinx-rtd-theme" },
+ { name = "tox" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "ipywidgets", marker = "extra == 'remote'" },
+ { name = "matplotlib", specifier = ">=3.5.3" },
+ { name = "notebook", marker = "extra == 'example-notebooks'" },
+ { name = "notebook", marker = "extra == 'remote'" },
+ { name = "pyamapping" },
+ { name = "pyaudio", marker = "extra == 'pyaudio'", specifier = ">=0.2.12" },
+ { name = "scipy", specifier = ">=1.7.3" },
+ { name = "soundfile", specifier = ">=0.13.0" },
+ { name = "websocket", marker = "extra == 'remote'" },
+]
+provides-extras = ["example-notebooks", "pyaudio", "remote"]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "myst-parser" },
+ { name = "pre-commit" },
+ { name = "pydocstyle" },
+ { name = "pytest" },
+ { name = "pytest-cov" },
+ { name = "sphinx", specifier = "==7.2.6" },
+ { name = "sphinx-rtd-theme", specifier = "==2.0.0" },
+ { name = "tox" },
+]
+
+[[package]]
+name = "pyamapping"
+version = "0.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/8b/fa/500657cf5b6f446b93d8492c1af728a0896283a256785a354d670bee15ec/pyamapping-0.1.0.tar.gz", hash = "sha256:20f75d8fc0f2fb9cd953954f3f7e8ecbea171a71fb7aef2d11b7824fba65c7ae", size = 22581 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d2/9b/bf0a5232859bf0f71a413bdac166d767a5148cc05e09a4450dc6e3ae5bce/pyamapping-0.1.0-py3-none-any.whl", hash = "sha256:1d11c926df305c85325c6fb3e78848f614631d62d4c384e559adb455e9551b12", size = 4908 },
+]
+
+[[package]]
+name = "pyaudio"
+version = "0.2.14"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/26/1d/8878c7752febb0f6716a7e1a52cb92ac98871c5aa522cba181878091607c/PyAudio-0.2.14.tar.gz", hash = "sha256:78dfff3879b4994d1f4fc6485646a57755c6ee3c19647a491f790a0895bd2f87", size = 47066 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/f0/b0eab89eafa70a86b7b566a4df2f94c7880a2d483aa8de1c77d335335b5b/PyAudio-0.2.14-cp311-cp311-win32.whl", hash = "sha256:506b32a595f8693811682ab4b127602d404df7dfc453b499c91a80d0f7bad289", size = 144624 },
+ { url = "https://files.pythonhosted.org/packages/82/d8/f043c854aad450a76e476b0cf9cda1956419e1dacf1062eb9df3c0055abe/PyAudio-0.2.14-cp311-cp311-win_amd64.whl", hash = "sha256:bbeb01d36a2f472ae5ee5e1451cacc42112986abe622f735bb870a5db77cf903", size = 164070 },
+ { url = "https://files.pythonhosted.org/packages/8d/45/8d2b76e8f6db783f9326c1305f3f816d4a12c8eda5edc6a2e1d03c097c3b/PyAudio-0.2.14-cp312-cp312-win32.whl", hash = "sha256:5fce4bcdd2e0e8c063d835dbe2860dac46437506af509353c7f8114d4bacbd5b", size = 144750 },
+ { url = "https://files.pythonhosted.org/packages/b0/6a/d25812e5f79f06285767ec607b39149d02aa3b31d50c2269768f48768930/PyAudio-0.2.14-cp312-cp312-win_amd64.whl", hash = "sha256:12f2f1ba04e06ff95d80700a78967897a489c05e093e3bffa05a84ed9c0a7fa3", size = 164126 },
+ { url = "https://files.pythonhosted.org/packages/3a/77/66cd37111a87c1589b63524f3d3c848011d21ca97828422c7fde7665ff0d/PyAudio-0.2.14-cp313-cp313-win32.whl", hash = "sha256:95328285b4dab57ea8c52a4a996cb52be6d629353315be5bfda403d15932a497", size = 150982 },
+ { url = "https://files.pythonhosted.org/packages/a5/8b/7f9a061c1cc2b230f9ac02a6003fcd14c85ce1828013aecbaf45aa988d20/PyAudio-0.2.14-cp313-cp313-win_amd64.whl", hash = "sha256:692d8c1446f52ed2662120bcd9ddcb5aa2b71f38bda31e58b19fb4672fffba69", size = 173655 },
+]
+
+[[package]]
+name = "pycparser"
+version = "2.23"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140 },
+]
+
+[[package]]
+name = "pydocstyle"
+version = "6.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "snowballstemmer" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e9/5c/d5385ca59fd065e3c6a5fe19f9bc9d5ea7f2509fa8c9c22fb6b2031dd953/pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1", size = 36796 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/36/ea/99ddefac41971acad68f14114f38261c1f27dac0b3ec529824ebc739bdaa/pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019", size = 38038 },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151 },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781 },
+]
+
+[[package]]
+name = "pyproject-api"
+version = "1.10.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "packaging" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/45/7b/c0e1333b61d41c69e59e5366e727b18c4992688caf0de1be10b3e5265f6b/pyproject_api-1.10.0.tar.gz", hash = "sha256:40c6f2d82eebdc4afee61c773ed208c04c19db4c4a60d97f8d7be3ebc0bbb330", size = 22785 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/cc/cecf97be298bee2b2a37dd360618c819a2a7fd95251d8e480c1f0eb88f3b/pyproject_api-1.10.0-py3-none-any.whl", hash = "sha256:8757c41a79c0f4ab71b99abed52b97ecf66bd20b04fa59da43b5840bac105a09", size = 13218 },
+]
+
+[[package]]
+name = "pytest"
+version = "9.0.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249 },
+]
+
+[[package]]
+name = "pytest-cov"
+version = "7.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "coverage", extra = ["toml"] },
+ { name = "pluggy" },
+ { name = "pytest" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876 },
+]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
+]
+
+[[package]]
+name = "python-discovery"
+version = "1.2.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "filelock" },
+ { name = "platformdirs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb", size = 58872 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a", size = 31894 },
+]
+
+[[package]]
+name = "python-json-logger"
+version = "4.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f7/ff/3cc9165fd44106973cd7ac9facb674a65ed853494592541d339bdc9a30eb/python_json_logger-4.1.0.tar.gz", hash = "sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195", size = 17573 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/27/be/0631a861af4d1c875f096c07d34e9a63639560a717130e7a87cbc82b7e3f/python_json_logger-4.1.0-py3-none-any.whl", hash = "sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2", size = 15021 },
+]
+
+[[package]]
+name = "pywinpty"
+version = "3.0.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f7/54/37c7370ba91f579235049dc26cd2c5e657d2a943e01820844ffc81f32176/pywinpty-3.0.3.tar.gz", hash = "sha256:523441dc34d231fb361b4b00f8c99d3f16de02f5005fd544a0183112bcc22412", size = 31309 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/79/c3/3e75075c7f71735f22b66fab0481f2c98e3a4d58cba55cb50ba29114bcf6/pywinpty-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:dff25a9a6435f527d7c65608a7e62783fc12076e7d44487a4911ee91be5a8ac8", size = 2114430 },
+ { url = "https://files.pythonhosted.org/packages/8d/1e/8a54166a8c5e4f5cb516514bdf4090be4d51a71e8d9f6d98c0aa00fe45d4/pywinpty-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:fbc1e230e5b193eef4431cba3f39996a288f9958f9c9f092c8a961d930ee8f68", size = 236191 },
+ { url = "https://files.pythonhosted.org/packages/7c/d4/aeb5e1784d2c5bff6e189138a9ca91a090117459cea0c30378e1f2db3d54/pywinpty-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c9081df0e49ffa86d15db4a6ba61530630e48707f987df42c9d3313537e81fc0", size = 2113098 },
+ { url = "https://files.pythonhosted.org/packages/b9/53/7278223c493ccfe4883239cf06c823c56460a8010e0fc778eef67858dc14/pywinpty-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:15e79d870e18b678fb8a5a6105fd38496b55697c66e6fc0378236026bc4d59e9", size = 234901 },
+ { url = "https://files.pythonhosted.org/packages/e5/cb/58d6ed3fd429c96a90ef01ac9a617af10a6d41469219c25e7dc162abbb71/pywinpty-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9c91dbb026050c77bdcef964e63a4f10f01a639113c4d3658332614544c467ab", size = 2112686 },
+ { url = "https://files.pythonhosted.org/packages/fd/50/724ed5c38c504d4e58a88a072776a1e880d970789deaeb2b9f7bd9a5141a/pywinpty-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:fe1f7911805127c94cf51f89ab14096c6f91ffdcacf993d2da6082b2142a2523", size = 234591 },
+ { url = "https://files.pythonhosted.org/packages/f7/ad/90a110538696b12b39fd8758a06d70ded899308198ad2305ac68e361126e/pywinpty-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:3f07a6cf1c1d470d284e614733c3d0f726d2c85e78508ea10a403140c3c0c18a", size = 2112360 },
+ { url = "https://files.pythonhosted.org/packages/44/0f/7ffa221757a220402bc79fda44044c3f2cc57338d878ab7d622add6f4581/pywinpty-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:15c7c0b6f8e9d87aabbaff76468dabf6e6121332c40fc1d83548d02a9d6a3759", size = 233107 },
+ { url = "https://files.pythonhosted.org/packages/28/88/2ff917caff61e55f38bcdb27de06ee30597881b2cae44fbba7627be015c4/pywinpty-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:d4b6b7b0fe0cdcd02e956bd57cfe9f4e5a06514eecf3b5ae174da4f951b58be9", size = 2113282 },
+ { url = "https://files.pythonhosted.org/packages/63/32/40a775343ace542cc43ece3f1d1fce454021521ecac41c4c4573081c2336/pywinpty-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:34789d685fc0d547ce0c8a65e5a70e56f77d732fa6e03c8f74fefb8cbb252019", size = 234207 },
+ { url = "https://files.pythonhosted.org/packages/8d/54/5d5e52f4cb75028104ca6faf36c10f9692389b1986d34471663b4ebebd6d/pywinpty-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0c37e224a47a971d1a6e08649a1714dac4f63c11920780977829ed5c8cadead1", size = 2112910 },
+ { url = "https://files.pythonhosted.org/packages/0a/44/dcd184824e21d4620b06c7db9fbb15c3ad0a0f1fa2e6de79969fb82647ec/pywinpty-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:c4e9c3dff7d86ba81937438d5819f19f385a39d8f592d4e8af67148ceb4f6ab5", size = 233425 },
+]
+
+[[package]]
+name = "pyyaml"
+version = "6.0.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826 },
+ { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577 },
+ { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556 },
+ { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114 },
+ { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638 },
+ { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463 },
+ { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986 },
+ { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543 },
+ { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763 },
+ { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063 },
+ { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973 },
+ { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116 },
+ { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011 },
+ { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870 },
+ { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089 },
+ { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181 },
+ { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658 },
+ { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003 },
+ { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344 },
+ { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669 },
+ { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252 },
+ { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081 },
+ { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159 },
+ { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626 },
+ { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613 },
+ { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115 },
+ { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427 },
+ { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090 },
+ { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246 },
+ { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814 },
+ { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809 },
+ { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454 },
+ { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355 },
+ { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175 },
+ { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228 },
+ { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194 },
+ { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429 },
+ { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912 },
+ { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108 },
+ { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641 },
+ { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901 },
+ { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132 },
+ { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261 },
+ { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272 },
+ { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923 },
+ { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062 },
+ { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341 },
+]
+
+[[package]]
+name = "pyzmq"
+version = "27.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cffi", marker = "implementation_name == 'pypy'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86", size = 1333328 },
+ { url = "https://files.pythonhosted.org/packages/bd/a0/fc7e78a23748ad5443ac3275943457e8452da67fda347e05260261108cbc/pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581", size = 908803 },
+ { url = "https://files.pythonhosted.org/packages/7e/22/37d15eb05f3bdfa4abea6f6d96eb3bb58585fbd3e4e0ded4e743bc650c97/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f", size = 668836 },
+ { url = "https://files.pythonhosted.org/packages/b1/c4/2a6fe5111a01005fc7af3878259ce17684fabb8852815eda6225620f3c59/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e", size = 857038 },
+ { url = "https://files.pythonhosted.org/packages/cb/eb/bfdcb41d0db9cd233d6fb22dc131583774135505ada800ebf14dfb0a7c40/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e", size = 1657531 },
+ { url = "https://files.pythonhosted.org/packages/ab/21/e3180ca269ed4a0de5c34417dfe71a8ae80421198be83ee619a8a485b0c7/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2", size = 2034786 },
+ { url = "https://files.pythonhosted.org/packages/3b/b1/5e21d0b517434b7f33588ff76c177c5a167858cc38ef740608898cd329f2/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394", size = 1894220 },
+ { url = "https://files.pythonhosted.org/packages/03/f2/44913a6ff6941905efc24a1acf3d3cb6146b636c546c7406c38c49c403d4/pyzmq-27.1.0-cp311-cp311-win32.whl", hash = "sha256:6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f", size = 567155 },
+ { url = "https://files.pythonhosted.org/packages/23/6d/d8d92a0eb270a925c9b4dd039c0b4dc10abc2fcbc48331788824ef113935/pyzmq-27.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97", size = 633428 },
+ { url = "https://files.pythonhosted.org/packages/ae/14/01afebc96c5abbbd713ecfc7469cfb1bc801c819a74ed5c9fad9a48801cb/pyzmq-27.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07", size = 559497 },
+ { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279 },
+ { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645 },
+ { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574 },
+ { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995 },
+ { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070 },
+ { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121 },
+ { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550 },
+ { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184 },
+ { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480 },
+ { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993 },
+ { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436 },
+ { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301 },
+ { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197 },
+ { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275 },
+ { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469 },
+ { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961 },
+ { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282 },
+ { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468 },
+ { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394 },
+ { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964 },
+ { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029 },
+ { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541 },
+ { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197 },
+ { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175 },
+ { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427 },
+ { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929 },
+ { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193 },
+ { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388 },
+ { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316 },
+ { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472 },
+ { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401 },
+ { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170 },
+ { url = "https://files.pythonhosted.org/packages/4c/c6/c4dcdecdbaa70969ee1fdced6d7b8f60cfabe64d25361f27ac4665a70620/pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066", size = 836265 },
+ { url = "https://files.pythonhosted.org/packages/3e/79/f38c92eeaeb03a2ccc2ba9866f0439593bb08c5e3b714ac1d553e5c96e25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604", size = 800208 },
+ { url = "https://files.pythonhosted.org/packages/49/0e/3f0d0d335c6b3abb9b7b723776d0b21fa7f3a6c819a0db6097059aada160/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c", size = 567747 },
+ { url = "https://files.pythonhosted.org/packages/a1/cf/f2b3784d536250ffd4be70e049f3b60981235d70c6e8ce7e3ef21e1adb25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271", size = 747371 },
+ { url = "https://files.pythonhosted.org/packages/01/1b/5dbe84eefc86f48473947e2f41711aded97eecef1231f4558f1f02713c12/pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355", size = 544862 },
+]
+
+[[package]]
+name = "referencing"
+version = "0.37.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "rpds-py" },
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766 },
+]
+
+[[package]]
+name = "requests"
+version = "2.33.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "charset-normalizer" },
+ { name = "idna" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/5f/a4/98b9c7c6428a668bf7e42ebb7c79d576a1c3c1e3ae2d47e674b468388871/requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", size = 134120 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a", size = 64947 },
+]
+
+[[package]]
+name = "rfc3339-validator"
+version = "0.1.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490 },
+]
+
+[[package]]
+name = "rfc3986-validator"
+version = "0.1.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242 },
+]
+
+[[package]]
+name = "rfc3987-syntax"
+version = "1.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "lark" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046 },
+]
+
+[[package]]
+name = "rpds-py"
+version = "0.30.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4d/6e/f964e88b3d2abee2a82c1ac8366da848fce1c6d834dc2132c3fda3970290/rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425", size = 370157 },
+ { url = "https://files.pythonhosted.org/packages/94/ba/24e5ebb7c1c82e74c4e4f33b2112a5573ddc703915b13a073737b59b86e0/rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d", size = 359676 },
+ { url = "https://files.pythonhosted.org/packages/84/86/04dbba1b087227747d64d80c3b74df946b986c57af0a9f0c98726d4d7a3b/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4", size = 389938 },
+ { url = "https://files.pythonhosted.org/packages/42/bb/1463f0b1722b7f45431bdd468301991d1328b16cffe0b1c2918eba2c4eee/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f", size = 402932 },
+ { url = "https://files.pythonhosted.org/packages/99/ee/2520700a5c1f2d76631f948b0736cdf9b0acb25abd0ca8e889b5c62ac2e3/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4", size = 525830 },
+ { url = "https://files.pythonhosted.org/packages/e0/ad/bd0331f740f5705cc555a5e17fdf334671262160270962e69a2bdef3bf76/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97", size = 412033 },
+ { url = "https://files.pythonhosted.org/packages/f8/1e/372195d326549bb51f0ba0f2ecb9874579906b97e08880e7a65c3bef1a99/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89", size = 390828 },
+ { url = "https://files.pythonhosted.org/packages/ab/2b/d88bb33294e3e0c76bc8f351a3721212713629ffca1700fa94979cb3eae8/rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d", size = 404683 },
+ { url = "https://files.pythonhosted.org/packages/50/32/c759a8d42bcb5289c1fac697cd92f6fe01a018dd937e62ae77e0e7f15702/rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038", size = 421583 },
+ { url = "https://files.pythonhosted.org/packages/2b/81/e729761dbd55ddf5d84ec4ff1f47857f4374b0f19bdabfcf929164da3e24/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7", size = 572496 },
+ { url = "https://files.pythonhosted.org/packages/14/f6/69066a924c3557c9c30baa6ec3a0aa07526305684c6f86c696b08860726c/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed", size = 598669 },
+ { url = "https://files.pythonhosted.org/packages/5f/48/905896b1eb8a05630d20333d1d8ffd162394127b74ce0b0784ae04498d32/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85", size = 561011 },
+ { url = "https://files.pythonhosted.org/packages/22/16/cd3027c7e279d22e5eb431dd3c0fbc677bed58797fe7581e148f3f68818b/rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c", size = 221406 },
+ { url = "https://files.pythonhosted.org/packages/fa/5b/e7b7aa136f28462b344e652ee010d4de26ee9fd16f1bfd5811f5153ccf89/rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825", size = 236024 },
+ { url = "https://files.pythonhosted.org/packages/14/a6/364bba985e4c13658edb156640608f2c9e1d3ea3c81b27aa9d889fff0e31/rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229", size = 229069 },
+ { url = "https://files.pythonhosted.org/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086 },
+ { url = "https://files.pythonhosted.org/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053 },
+ { url = "https://files.pythonhosted.org/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763 },
+ { url = "https://files.pythonhosted.org/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951 },
+ { url = "https://files.pythonhosted.org/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622 },
+ { url = "https://files.pythonhosted.org/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492 },
+ { url = "https://files.pythonhosted.org/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080 },
+ { url = "https://files.pythonhosted.org/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680 },
+ { url = "https://files.pythonhosted.org/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589 },
+ { url = "https://files.pythonhosted.org/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289 },
+ { url = "https://files.pythonhosted.org/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737 },
+ { url = "https://files.pythonhosted.org/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120 },
+ { url = "https://files.pythonhosted.org/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782 },
+ { url = "https://files.pythonhosted.org/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463 },
+ { url = "https://files.pythonhosted.org/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868 },
+ { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887 },
+ { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904 },
+ { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945 },
+ { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783 },
+ { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021 },
+ { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589 },
+ { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025 },
+ { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895 },
+ { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799 },
+ { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731 },
+ { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027 },
+ { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020 },
+ { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139 },
+ { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224 },
+ { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645 },
+ { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443 },
+ { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375 },
+ { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850 },
+ { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812 },
+ { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841 },
+ { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149 },
+ { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843 },
+ { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507 },
+ { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949 },
+ { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790 },
+ { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217 },
+ { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806 },
+ { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341 },
+ { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768 },
+ { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099 },
+ { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192 },
+ { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080 },
+ { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841 },
+ { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670 },
+ { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005 },
+ { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112 },
+ { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049 },
+ { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661 },
+ { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606 },
+ { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126 },
+ { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371 },
+ { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298 },
+ { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604 },
+ { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391 },
+ { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868 },
+ { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747 },
+ { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795 },
+ { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330 },
+ { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194 },
+ { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340 },
+ { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765 },
+ { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834 },
+ { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470 },
+ { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630 },
+ { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148 },
+ { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030 },
+ { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570 },
+ { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532 },
+ { url = "https://files.pythonhosted.org/packages/69/71/3f34339ee70521864411f8b6992e7ab13ac30d8e4e3309e07c7361767d91/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58", size = 372292 },
+ { url = "https://files.pythonhosted.org/packages/57/09/f183df9b8f2d66720d2ef71075c59f7e1b336bec7ee4c48f0a2b06857653/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a", size = 362128 },
+ { url = "https://files.pythonhosted.org/packages/7a/68/5c2594e937253457342e078f0cc1ded3dd7b2ad59afdbf2d354869110a02/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb", size = 391542 },
+ { url = "https://files.pythonhosted.org/packages/49/5c/31ef1afd70b4b4fbdb2800249f34c57c64beb687495b10aec0365f53dfc4/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c", size = 404004 },
+ { url = "https://files.pythonhosted.org/packages/e3/63/0cfbea38d05756f3440ce6534d51a491d26176ac045e2707adc99bb6e60a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3", size = 527063 },
+ { url = "https://files.pythonhosted.org/packages/42/e6/01e1f72a2456678b0f618fc9a1a13f882061690893c192fcad9f2926553a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5", size = 413099 },
+ { url = "https://files.pythonhosted.org/packages/b8/25/8df56677f209003dcbb180765520c544525e3ef21ea72279c98b9aa7c7fb/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738", size = 392177 },
+ { url = "https://files.pythonhosted.org/packages/4a/b4/0a771378c5f16f8115f796d1f437950158679bcd2a7c68cf251cfb00ed5b/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f", size = 406015 },
+ { url = "https://files.pythonhosted.org/packages/36/d8/456dbba0af75049dc6f63ff295a2f92766b9d521fa00de67a2bd6427d57a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877", size = 423736 },
+ { url = "https://files.pythonhosted.org/packages/13/64/b4d76f227d5c45a7e0b796c674fd81b0a6c4fbd48dc29271857d8219571c/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a", size = 573981 },
+ { url = "https://files.pythonhosted.org/packages/20/91/092bacadeda3edf92bf743cc96a7be133e13a39cdbfd7b5082e7ab638406/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4", size = 599782 },
+ { url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", size = 562191 },
+]
+
+[[package]]
+name = "scipy"
+version = "1.17.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/75/b4ce781849931fef6fd529afa6b63711d5a733065722d0c3e2724af9e40a/scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec", size = 31613675 },
+ { url = "https://files.pythonhosted.org/packages/f7/58/bccc2861b305abdd1b8663d6130c0b3d7cc22e8d86663edbc8401bfd40d4/scipy-1.17.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696", size = 28162057 },
+ { url = "https://files.pythonhosted.org/packages/6d/ee/18146b7757ed4976276b9c9819108adbc73c5aad636e5353e20746b73069/scipy-1.17.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a3472cfbca0a54177d0faa68f697d8ba4c80bbdc19908c3465556d9f7efce9ee", size = 20334032 },
+ { url = "https://files.pythonhosted.org/packages/ec/e6/cef1cf3557f0c54954198554a10016b6a03b2ec9e22a4e1df734936bd99c/scipy-1.17.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:766e0dc5a616d026a3a1cffa379af959671729083882f50307e18175797b3dfd", size = 22709533 },
+ { url = "https://files.pythonhosted.org/packages/4d/60/8804678875fc59362b0fb759ab3ecce1f09c10a735680318ac30da8cd76b/scipy-1.17.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:744b2bf3640d907b79f3fd7874efe432d1cf171ee721243e350f55234b4cec4c", size = 33062057 },
+ { url = "https://files.pythonhosted.org/packages/09/7d/af933f0f6e0767995b4e2d705a0665e454d1c19402aa7e895de3951ebb04/scipy-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43af8d1f3bea642559019edfe64e9b11192a8978efbd1539d7bc2aaa23d92de4", size = 35349300 },
+ { url = "https://files.pythonhosted.org/packages/b4/3d/7ccbbdcbb54c8fdc20d3b6930137c782a163fa626f0aef920349873421ba/scipy-1.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd96a1898c0a47be4520327e01f874acfd61fb48a9420f8aa9f6483412ffa444", size = 35127333 },
+ { url = "https://files.pythonhosted.org/packages/e8/19/f926cb11c42b15ba08e3a71e376d816ac08614f769b4f47e06c3580c836a/scipy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4eb6c25dd62ee8d5edf68a8e1c171dd71c292fdae95d8aeb3dd7d7de4c364082", size = 37741314 },
+ { url = "https://files.pythonhosted.org/packages/95/da/0d1df507cf574b3f224ccc3d45244c9a1d732c81dcb26b1e8a766ae271a8/scipy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:d30e57c72013c2a4fe441c2fcb8e77b14e152ad48b5464858e07e2ad9fbfceff", size = 36607512 },
+ { url = "https://files.pythonhosted.org/packages/68/7f/bdd79ceaad24b671543ffe0ef61ed8e659440eb683b66f033454dcee90eb/scipy-1.17.1-cp311-cp311-win_arm64.whl", hash = "sha256:9ecb4efb1cd6e8c4afea0daa91a87fbddbce1b99d2895d151596716c0b2e859d", size = 24599248 },
+ { url = "https://files.pythonhosted.org/packages/35/48/b992b488d6f299dbe3f11a20b24d3dda3d46f1a635ede1c46b5b17a7b163/scipy-1.17.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:35c3a56d2ef83efc372eaec584314bd0ef2e2f0d2adb21c55e6ad5b344c0dcb8", size = 31610954 },
+ { url = "https://files.pythonhosted.org/packages/b2/02/cf107b01494c19dc100f1d0b7ac3cc08666e96ba2d64db7626066cee895e/scipy-1.17.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fcb310ddb270a06114bb64bbe53c94926b943f5b7f0842194d585c65eb4edd76", size = 28172662 },
+ { url = "https://files.pythonhosted.org/packages/cf/a9/599c28631bad314d219cf9ffd40e985b24d603fc8a2f4ccc5ae8419a535b/scipy-1.17.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086", size = 20344366 },
+ { url = "https://files.pythonhosted.org/packages/35/f5/906eda513271c8deb5af284e5ef0206d17a96239af79f9fa0aebfe0e36b4/scipy-1.17.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:c80be5ede8f3f8eded4eff73cc99a25c388ce98e555b17d31da05287015ffa5b", size = 22704017 },
+ { url = "https://files.pythonhosted.org/packages/da/34/16f10e3042d2f1d6b66e0428308ab52224b6a23049cb2f5c1756f713815f/scipy-1.17.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e19ebea31758fac5893a2ac360fedd00116cbb7628e650842a6691ba7ca28a21", size = 32927842 },
+ { url = "https://files.pythonhosted.org/packages/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458", size = 35235890 },
+ { url = "https://files.pythonhosted.org/packages/c5/5c/9d7f4c88bea6e0d5a4f1bc0506a53a00e9fcb198de372bfe4d3652cef482/scipy-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a604bae87c6195d8b1045eddece0514d041604b14f2727bbc2b3020172045eb", size = 35003557 },
+ { url = "https://files.pythonhosted.org/packages/65/94/7698add8f276dbab7a9de9fb6b0e02fc13ee61d51c7c3f85ac28b65e1239/scipy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f590cd684941912d10becc07325a3eeb77886fe981415660d9265c4c418d0bea", size = 37625856 },
+ { url = "https://files.pythonhosted.org/packages/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87", size = 36549682 },
+ { url = "https://files.pythonhosted.org/packages/bc/98/fe9ae9ffb3b54b62559f52dedaebe204b408db8109a8c66fdd04869e6424/scipy-1.17.1-cp312-cp312-win_arm64.whl", hash = "sha256:f4115102802df98b2b0db3cce5cb9b92572633a1197c77b7553e5203f284a5b3", size = 24547340 },
+ { url = "https://files.pythonhosted.org/packages/76/27/07ee1b57b65e92645f219b37148a7e7928b82e2b5dbeccecb4dff7c64f0b/scipy-1.17.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c", size = 31590199 },
+ { url = "https://files.pythonhosted.org/packages/ec/ae/db19f8ab842e9b724bf5dbb7db29302a91f1e55bc4d04b1025d6d605a2c5/scipy-1.17.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f", size = 28154001 },
+ { url = "https://files.pythonhosted.org/packages/5b/58/3ce96251560107b381cbd6e8413c483bbb1228a6b919fa8652b0d4090e7f/scipy-1.17.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d", size = 20325719 },
+ { url = "https://files.pythonhosted.org/packages/b2/83/15087d945e0e4d48ce2377498abf5ad171ae013232ae31d06f336e64c999/scipy-1.17.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b", size = 22683595 },
+ { url = "https://files.pythonhosted.org/packages/b4/e0/e58fbde4a1a594c8be8114eb4aac1a55bcd6587047efc18a61eb1f5c0d30/scipy-1.17.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6", size = 32896429 },
+ { url = "https://files.pythonhosted.org/packages/f5/5f/f17563f28ff03c7b6799c50d01d5d856a1d55f2676f537ca8d28c7f627cd/scipy-1.17.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464", size = 35203952 },
+ { url = "https://files.pythonhosted.org/packages/8d/a5/9afd17de24f657fdfe4df9a3f1ea049b39aef7c06000c13db1530d81ccca/scipy-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950", size = 34979063 },
+ { url = "https://files.pythonhosted.org/packages/8b/13/88b1d2384b424bf7c924f2038c1c409f8d88bb2a8d49d097861dd64a57b2/scipy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369", size = 37598449 },
+ { url = "https://files.pythonhosted.org/packages/35/e5/d6d0e51fc888f692a35134336866341c08655d92614f492c6860dc45bb2c/scipy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448", size = 36510943 },
+ { url = "https://files.pythonhosted.org/packages/2a/fd/3be73c564e2a01e690e19cc618811540ba5354c67c8680dce3281123fb79/scipy-1.17.1-cp313-cp313-win_arm64.whl", hash = "sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87", size = 24545621 },
+ { url = "https://files.pythonhosted.org/packages/6f/6b/17787db8b8114933a66f9dcc479a8272e4b4da75fe03b0c282f7b0ade8cd/scipy-1.17.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a", size = 31936708 },
+ { url = "https://files.pythonhosted.org/packages/38/2e/524405c2b6392765ab1e2b722a41d5da33dc5c7b7278184a8ad29b6cb206/scipy-1.17.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0", size = 28570135 },
+ { url = "https://files.pythonhosted.org/packages/fd/c3/5bd7199f4ea8556c0c8e39f04ccb014ac37d1468e6cfa6a95c6b3562b76e/scipy-1.17.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce", size = 20741977 },
+ { url = "https://files.pythonhosted.org/packages/d9/b8/8ccd9b766ad14c78386599708eb745f6b44f08400a5fd0ade7cf89b6fc93/scipy-1.17.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6", size = 23029601 },
+ { url = "https://files.pythonhosted.org/packages/6d/a0/3cb6f4d2fb3e17428ad2880333cac878909ad1a89f678527b5328b93c1d4/scipy-1.17.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e", size = 33019667 },
+ { url = "https://files.pythonhosted.org/packages/f3/c3/2d834a5ac7bf3a0c806ad1508efc02dda3c8c61472a56132d7894c312dea/scipy-1.17.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475", size = 35264159 },
+ { url = "https://files.pythonhosted.org/packages/4d/77/d3ed4becfdbd217c52062fafe35a72388d1bd82c2d0ba5ca19d6fcc93e11/scipy-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50", size = 35102771 },
+ { url = "https://files.pythonhosted.org/packages/bd/12/d19da97efde68ca1ee5538bb261d5d2c062f0c055575128f11a2730e3ac1/scipy-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca", size = 37665910 },
+ { url = "https://files.pythonhosted.org/packages/06/1c/1172a88d507a4baaf72c5a09bb6c018fe2ae0ab622e5830b703a46cc9e44/scipy-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c", size = 36562980 },
+ { url = "https://files.pythonhosted.org/packages/70/b0/eb757336e5a76dfa7911f63252e3b7d1de00935d7705cf772db5b45ec238/scipy-1.17.1-cp313-cp313t-win_arm64.whl", hash = "sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49", size = 24856543 },
+ { url = "https://files.pythonhosted.org/packages/cf/83/333afb452af6f0fd70414dc04f898647ee1423979ce02efa75c3b0f2c28e/scipy-1.17.1-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:a48a72c77a310327f6a3a920092fa2b8fd03d7deaa60f093038f22d98e096717", size = 31584510 },
+ { url = "https://files.pythonhosted.org/packages/ed/a6/d05a85fd51daeb2e4ea71d102f15b34fedca8e931af02594193ae4fd25f7/scipy-1.17.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:45abad819184f07240d8a696117a7aacd39787af9e0b719d00285549ed19a1e9", size = 28170131 },
+ { url = "https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b", size = 20342032 },
+ { url = "https://files.pythonhosted.org/packages/c9/35/2c342897c00775d688d8ff3987aced3426858fd89d5a0e26e020b660b301/scipy-1.17.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7bdf2da170b67fdf10bca777614b1c7d96ae3ca5794fd9587dce41eb2966e866", size = 22678766 },
+ { url = "https://files.pythonhosted.org/packages/ef/f2/7cdb8eb308a1a6ae1e19f945913c82c23c0c442a462a46480ce487fdc0ac/scipy-1.17.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:adb2642e060a6549c343603a3851ba76ef0b74cc8c079a9a58121c7ec9fe2350", size = 32957007 },
+ { url = "https://files.pythonhosted.org/packages/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118", size = 35221333 },
+ { url = "https://files.pythonhosted.org/packages/d9/77/5b8509d03b77f093a0d52e606d3c4f79e8b06d1d38c441dacb1e26cacf46/scipy-1.17.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d2650c1fb97e184d12d8ba010493ee7b322864f7d3d00d3f9bb97d9c21de4068", size = 35042066 },
+ { url = "https://files.pythonhosted.org/packages/f9/df/18f80fb99df40b4070328d5ae5c596f2f00fffb50167e31439e932f29e7d/scipy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:08b900519463543aa604a06bec02461558a6e1cef8fdbb8098f77a48a83c8118", size = 37612763 },
+ { url = "https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19", size = 37290984 },
+ { url = "https://files.pythonhosted.org/packages/7c/56/fe201e3b0f93d1a8bcf75d3379affd228a63d7e2d80ab45467a74b494947/scipy-1.17.1-cp314-cp314-win_arm64.whl", hash = "sha256:f8885db0bc2bffa59d5c1b72fad7a6a92d3e80e7257f967dd81abb553a90d293", size = 25192877 },
+ { url = "https://files.pythonhosted.org/packages/96/ad/f8c414e121f82e02d76f310f16db9899c4fcde36710329502a6b2a3c0392/scipy-1.17.1-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:1cc682cea2ae55524432f3cdff9e9a3be743d52a7443d0cba9017c23c87ae2f6", size = 31949750 },
+ { url = "https://files.pythonhosted.org/packages/7c/b0/c741e8865d61b67c81e255f4f0a832846c064e426636cd7de84e74d209be/scipy-1.17.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:2040ad4d1795a0ae89bfc7e8429677f365d45aa9fd5e4587cf1ea737f927b4a1", size = 28585858 },
+ { url = "https://files.pythonhosted.org/packages/ed/1b/3985219c6177866628fa7c2595bfd23f193ceebbe472c98a08824b9466ff/scipy-1.17.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:131f5aaea57602008f9822e2115029b55d4b5f7c070287699fe45c661d051e39", size = 20757723 },
+ { url = "https://files.pythonhosted.org/packages/c0/19/2a04aa25050d656d6f7b9e7b685cc83d6957fb101665bfd9369ca6534563/scipy-1.17.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9cdc1a2fcfd5c52cfb3045feb399f7b3ce822abdde3a193a6b9a60b3cb5854ca", size = 23043098 },
+ { url = "https://files.pythonhosted.org/packages/86/f1/3383beb9b5d0dbddd030335bf8a8b32d4317185efe495374f134d8be6cce/scipy-1.17.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e3dcd57ab780c741fde8dc68619de988b966db759a3c3152e8e9142c26295ad", size = 33030397 },
+ { url = "https://files.pythonhosted.org/packages/41/68/8f21e8a65a5a03f25a79165ec9d2b28c00e66dc80546cf5eb803aeeff35b/scipy-1.17.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9956e4d4f4a301ebf6cde39850333a6b6110799d470dbbb1e25326ac447f52a", size = 35281163 },
+ { url = "https://files.pythonhosted.org/packages/84/8d/c8a5e19479554007a5632ed7529e665c315ae7492b4f946b0deb39870e39/scipy-1.17.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a4328d245944d09fd639771de275701ccadf5f781ba0ff092ad141e017eccda4", size = 35116291 },
+ { url = "https://files.pythonhosted.org/packages/52/52/e57eceff0e342a1f50e274264ed47497b59e6a4e3118808ee58ddda7b74a/scipy-1.17.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a77cbd07b940d326d39a1d1b37817e2ee4d79cb30e7338f3d0cddffae70fcaa2", size = 37682317 },
+ { url = "https://files.pythonhosted.org/packages/11/2f/b29eafe4a3fbc3d6de9662b36e028d5f039e72d345e05c250e121a230dd4/scipy-1.17.1-cp314-cp314t-win_amd64.whl", hash = "sha256:eb092099205ef62cd1782b006658db09e2fed75bffcae7cc0d44052d8aa0f484", size = 37345327 },
+ { url = "https://files.pythonhosted.org/packages/07/39/338d9219c4e87f3e708f18857ecd24d22a0c3094752393319553096b98af/scipy-1.17.1-cp314-cp314t-win_arm64.whl", hash = "sha256:200e1050faffacc162be6a486a984a0497866ec54149a01270adc8a59b7c7d21", size = 25489165 },
+]
+
+[[package]]
+name = "send2trash"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610 },
+]
+
+[[package]]
+name = "setuptools"
+version = "82.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4f/db/cfac1baf10650ab4d1c111714410d2fbb77ac5a616db26775db562c8fab2/setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", size = 1152316 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb", size = 1006223 },
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
+]
+
+[[package]]
+name = "snowballstemmer"
+version = "3.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274 },
+]
+
+[[package]]
+name = "soundfile"
+version = "0.13.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cffi" },
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e1/41/9b873a8c055582859b239be17902a85339bec6a30ad162f98c9b0288a2cc/soundfile-0.13.1.tar.gz", hash = "sha256:b2c68dab1e30297317080a5b43df57e302584c49e2942defdde0acccc53f0e5b", size = 46156 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/64/28/e2a36573ccbcf3d57c00626a21fe51989380636e821b341d36ccca0c1c3a/soundfile-0.13.1-py2.py3-none-any.whl", hash = "sha256:a23c717560da2cf4c7b5ae1142514e0fd82d6bbd9dfc93a50423447142f2c445", size = 25751 },
+ { url = "https://files.pythonhosted.org/packages/ea/ab/73e97a5b3cc46bba7ff8650a1504348fa1863a6f9d57d7001c6b67c5f20e/soundfile-0.13.1-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:82dc664d19831933fe59adad199bf3945ad06d84bc111a5b4c0d3089a5b9ec33", size = 1142250 },
+ { url = "https://files.pythonhosted.org/packages/a0/e5/58fd1a8d7b26fc113af244f966ee3aecf03cb9293cb935daaddc1e455e18/soundfile-0.13.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:743f12c12c4054921e15736c6be09ac26b3b3d603aef6fd69f9dde68748f2593", size = 1101406 },
+ { url = "https://files.pythonhosted.org/packages/58/ae/c0e4a53d77cf6e9a04179535766b3321b0b9ced5f70522e4caf9329f0046/soundfile-0.13.1-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:9c9e855f5a4d06ce4213f31918653ab7de0c5a8d8107cd2427e44b42df547deb", size = 1235729 },
+ { url = "https://files.pythonhosted.org/packages/57/5e/70bdd9579b35003a489fc850b5047beeda26328053ebadc1fb60f320f7db/soundfile-0.13.1-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:03267c4e493315294834a0870f31dbb3b28a95561b80b134f0bd3cf2d5f0e618", size = 1313646 },
+ { url = "https://files.pythonhosted.org/packages/fe/df/8c11dc4dfceda14e3003bb81a0d0edcaaf0796dd7b4f826ea3e532146bba/soundfile-0.13.1-py2.py3-none-win32.whl", hash = "sha256:c734564fab7c5ddf8e9be5bf70bab68042cd17e9c214c06e365e20d64f9a69d5", size = 899881 },
+ { url = "https://files.pythonhosted.org/packages/14/e9/6b761de83277f2f02ded7e7ea6f07828ec78e4b229b80e4ca55dd205b9dc/soundfile-0.13.1-py2.py3-none-win_amd64.whl", hash = "sha256:1e70a05a0626524a69e9f0f4dd2ec174b4e9567f4d8b6c11d38b5c289be36ee9", size = 1019162 },
+]
+
+[[package]]
+name = "soupsieve"
+version = "2.8.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016 },
+]
+
+[[package]]
+name = "sphinx"
+version = "7.2.6"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "alabaster" },
+ { name = "babel" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "docutils" },
+ { name = "imagesize" },
+ { name = "jinja2" },
+ { name = "packaging" },
+ { name = "pygments" },
+ { name = "requests" },
+ { name = "snowballstemmer" },
+ { name = "sphinxcontrib-applehelp" },
+ { name = "sphinxcontrib-devhelp" },
+ { name = "sphinxcontrib-htmlhelp" },
+ { name = "sphinxcontrib-jsmath" },
+ { name = "sphinxcontrib-qthelp" },
+ { name = "sphinxcontrib-serializinghtml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/73/8e/6e51da4b26665b4b92b1944ea18b2d9c825e753e19180cc5bdc818d0ed3b/sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5", size = 7015183 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b2/b6/8ed35256aa530a9d3da15d20bdc0ba888d5364441bb50a5a83ee7827affe/sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560", size = 3207959 },
+]
+
+[[package]]
+name = "sphinx-rtd-theme"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "docutils" },
+ { name = "sphinx" },
+ { name = "sphinxcontrib-jquery" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/fe/33/2a35a9cdbfda9086bda11457bcc872173ab3565b16b6d7f6b3efaa6dc3d6/sphinx_rtd_theme-2.0.0.tar.gz", hash = "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b", size = 2785005 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ea/46/00fda84467815c29951a9c91e3ae7503c409ddad04373e7cfc78daad4300/sphinx_rtd_theme-2.0.0-py2.py3-none-any.whl", hash = "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586", size = 2824721 },
+]
+
+[[package]]
+name = "sphinxcontrib-applehelp"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300 },
+]
+
+[[package]]
+name = "sphinxcontrib-devhelp"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530 },
+]
+
+[[package]]
+name = "sphinxcontrib-htmlhelp"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705 },
+]
+
+[[package]]
+name = "sphinxcontrib-jquery"
+version = "4.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "sphinx" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/76/85/749bd22d1a68db7291c89e2ebca53f4306c3f205853cf31e9de279034c3c/sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae", size = 121104 },
+]
+
+[[package]]
+name = "sphinxcontrib-jsmath"
+version = "1.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071 },
+]
+
+[[package]]
+name = "sphinxcontrib-qthelp"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743 },
+]
+
+[[package]]
+name = "sphinxcontrib-serializinghtml"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072 },
+]
+
+[[package]]
+name = "stack-data"
+version = "0.6.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "asttokens" },
+ { name = "executing" },
+ { name = "pure-eval" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521 },
+]
+
+[[package]]
+name = "terminado"
+version = "0.18.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "ptyprocess", marker = "os_name != 'nt'" },
+ { name = "pywinpty", marker = "os_name == 'nt'" },
+ { name = "tornado" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154 },
+]
+
+[[package]]
+name = "tinycss2"
+version = "1.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "webencodings" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610 },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704 },
+ { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454 },
+ { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561 },
+ { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824 },
+ { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227 },
+ { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859 },
+ { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204 },
+ { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084 },
+ { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285 },
+ { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924 },
+ { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018 },
+ { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948 },
+ { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341 },
+ { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159 },
+ { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290 },
+ { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141 },
+ { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847 },
+ { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088 },
+ { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866 },
+ { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887 },
+ { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704 },
+ { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628 },
+ { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180 },
+ { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674 },
+ { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976 },
+ { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755 },
+ { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265 },
+ { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726 },
+ { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859 },
+ { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713 },
+ { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084 },
+ { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973 },
+ { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223 },
+ { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973 },
+ { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082 },
+ { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490 },
+ { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263 },
+ { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736 },
+ { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717 },
+ { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461 },
+ { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855 },
+ { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144 },
+ { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683 },
+ { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196 },
+ { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393 },
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583 },
+]
+
+[[package]]
+name = "tomli-w"
+version = "1.2.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675 },
+]
+
+[[package]]
+name = "tornado"
+version = "6.5.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9", size = 516006 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa", size = 445983 },
+ { url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521", size = 444246 },
+ { url = "https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5", size = 447229 },
+ { url = "https://files.pythonhosted.org/packages/34/01/74e034a30ef59afb4097ef8659515e96a39d910b712a89af76f5e4e1f93c/tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07", size = 448192 },
+ { url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e", size = 448039 },
+ { url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca", size = 447445 },
+ { url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7", size = 448582 },
+ { url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b", size = 448990 },
+ { url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6", size = 448016 },
+]
+
+[[package]]
+name = "tox"
+version = "4.53.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cachetools" },
+ { name = "colorama" },
+ { name = "filelock" },
+ { name = "packaging" },
+ { name = "platformdirs" },
+ { name = "pluggy" },
+ { name = "pyproject-api" },
+ { name = "python-discovery" },
+ { name = "tomli-w" },
+ { name = "virtualenv" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/04/01/d87a00063fa670ce4c48a9706b615a95ddf2c9ef5558d43af6071f166fd4/tox-4.53.0.tar.gz", hash = "sha256:62c780e42f87d34ee60f2ea20342156253794fdcbd6885fd797d98ee05009f22", size = 274048 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/16/03/02e2a03f3756cfb66e7e1bac41b06953f12cec75ddb961d56695d4d43dc4/tox-4.53.0-py3-none-any.whl", hash = "sha256:cc4e716d18c4889aa179d785175c438fa60c35deef20ce689ec288d8fb656096", size = 212164 },
+]
+
+[[package]]
+name = "traitlets"
+version = "5.14.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359 },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.15.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614 },
+]
+
+[[package]]
+name = "tzdata"
+version = "2025.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 },
+]
+
+[[package]]
+name = "uri-template"
+version = "1.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140 },
+]
+
+[[package]]
+name = "urllib3"
+version = "2.6.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584 },
+]
+
+[[package]]
+name = "virtualenv"
+version = "21.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "distlib" },
+ { name = "filelock" },
+ { name = "platformdirs" },
+ { name = "python-discovery" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/3f/8b/6331f7a7fe70131c301106ec1e7cf23e2501bf7d4ca3636805801ca191bb/virtualenv-21.3.0.tar.gz", hash = "sha256:733750db978ec95c2d8eb4feadaa57091002bce404cb39ba69899cf7bd28944e", size = 7614069 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl", hash = "sha256:4d28ee41f6d9ec8f1f00cd472b9ffbcedda1b3d3b9a575b5c94a2d004fd51bd7", size = 7594690 },
+]
+
+[[package]]
+name = "wcwidth"
+version = "0.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159", size = 159684 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", size = 94189 },
+]
+
+[[package]]
+name = "webcolors"
+version = "25.10.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905 },
+]
+
+[[package]]
+name = "webencodings"
+version = "0.5.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774 },
+]
+
+[[package]]
+name = "websocket"
+version = "0.2.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "gevent" },
+ { name = "greenlet" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f2/6d/a60d620ea575c885510c574909d2e3ed62129b121fa2df00ca1c81024c87/websocket-0.2.1.tar.gz", hash = "sha256:42b506fae914ac5ed654e23ba9742e6a342b1a1c3eb92632b6166c65256469a4", size = 195339 }
+
+[[package]]
+name = "websocket-client"
+version = "1.9.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616 },
+]
+
+[[package]]
+name = "widgetsnbextension"
+version = "4.0.15"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/bd/f4/c67440c7fb409a71b7404b7aefcd7569a9c0d6bd071299bf4198ae7a5d95/widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9", size = 1097402 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366", size = 2196503 },
+]
+
+[[package]]
+name = "zope-event"
+version = "6.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/93/41/faa10af34d48d9cd6fa0249a1162943ad84a9590bd1a06939981e6640416/zope_event-6.2.tar.gz", hash = "sha256:b97d5d6327067ee6b9dfcbdf606ade9ade70991e19c162e808ea39e5fcf0f8d3", size = 18958 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9e/33/848922889e946d4befc415c219fe516af75c49555d8e736e183bfd30db42/zope_event-6.2-py3-none-any.whl", hash = "sha256:5e755153ac4faf64c10a4b6dd3307680166a3edf65b38df22df592610f8fa874", size = 6525 },
+]
+
+[[package]]
+name = "zope-interface"
+version = "8.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9f/65/34a6e6e4dfa260c4c55ee02bb2fc53625e126ff0181485286cf0c9d453d6/zope_interface-8.4.tar.gz", hash = "sha256:9dbee7925a23aa6349738892c911019d4095a96cff487b743482073ecbc174a8", size = 257736 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/79/11/bd982648e1e62d7c06a56017fd88d1beea2ebc8d7a5972cce137e774aff2/zope_interface-8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8b733af6e89a2b0b8edf5ff7a37988fe4e1788806e84e72127b88c47858f0da6", size = 210908 },
+ { url = "https://files.pythonhosted.org/packages/2d/4f/fa87d3bd69d22b93fa5b968597a3dd0a297e44aa87e4611b0ca74c4aeec1/zope_interface-8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:265bad2df2ec070f23ff863249a89b408b11908fd4207662781fd18e3c6fc912", size = 211235 },
+ { url = "https://files.pythonhosted.org/packages/eb/74/67379f7df4400ee45299c5200f17ec6c493e8a120ff4e5e9d26b09e32956/zope_interface-8.4-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:e195e76767847afb5379ffd67690c17d3c6efdab58dc0e477cf81ac94d5a5a15", size = 259918 },
+ { url = "https://files.pythonhosted.org/packages/b2/4e/c5106672b5c0b9071ce988d54124277762c3085cf1bc72e965e7173f1c26/zope_interface-8.4-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ec1a56b6cf9a757cbbce9da38284a01473b92b96c1517eabd99150f51f1bb69", size = 264343 },
+ { url = "https://files.pythonhosted.org/packages/fe/49/270c11e54e01b96d2efc59acbeb006a4171b8fafb75926c27d2184c32949/zope_interface-8.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:04c2c9b58e9c177628715d85e94834efa807c1f9f0a2f57ae0f7b553e8266ac4", size = 265629 },
+ { url = "https://files.pythonhosted.org/packages/b9/03/4ef05ada2230f05f08f579c45b60f127cce2bf379148cb7c21401052ca9d/zope_interface-8.4-cp311-cp311-win_amd64.whl", hash = "sha256:376d0ef005a131b349e2088e302aa094fa23c826d2ec8a7db4b00fb33c71e0d9", size = 214595 },
+ { url = "https://files.pythonhosted.org/packages/6a/f6/22a304f4061d7ec02e20816d804ab0e844564055b25d471371173c44d73e/zope_interface-8.4-cp311-cp311-win_arm64.whl", hash = "sha256:caffd033b27e311b45e15f01923cc9e73c6bfd8e843b4532e29b59ee432bf893", size = 212904 },
+ { url = "https://files.pythonhosted.org/packages/b8/96/0017b980424125cf98a9851d8fd3e24939818b7a82ecdd19ae672bb2413f/zope_interface-8.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:84064876ed96ddd0744e3ad5d37134c758d77885e54113567792671405a02bac", size = 211604 },
+ { url = "https://files.pythonhosted.org/packages/59/4c/2cf5c45477fdd58a2c786d0c0d1817cbaaff8743d98ae72c643c4fe3be7b/zope_interface-8.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:81ed23698bfb588c48b1756129814b890febac971ff6c8a414f82601773145bb", size = 211783 },
+ { url = "https://files.pythonhosted.org/packages/fa/8c/efabdafc25ed44ef9c1084aad9870bb6c2c9b78e542684efe6865c0f0067/zope_interface-8.4-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:e0b9d7e958657fad414f8272afcdf0b8a873fbbb2bb6a6287232d2f11a232bf8", size = 264752 },
+ { url = "https://files.pythonhosted.org/packages/53/5a/c4d52c58d5fee4ff67cc02f0dec24d0e84428520f67a52f1e4086f0e7779/zope_interface-8.4-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:eef0a49e041f4dc4d2a6ab894b4fd0c5354e0e8037e731fb953531e59b0d3d33", size = 269829 },
+ { url = "https://files.pythonhosted.org/packages/16/d2/df8f339c93bb5adee695546ba90d0daa2917338a4792281f6b8e652a9328/zope_interface-8.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b302f955c36e924e1f4fe70dd9105ff06235857861c6ae72c3b10b016aeee99", size = 269452 },
+ { url = "https://files.pythonhosted.org/packages/17/4b/bd97b1a21bb2c16d66a42f6c7a43c0a5afcfaf14c68d3b7d2ee6afb28e52/zope_interface-8.4-cp312-cp312-win_amd64.whl", hash = "sha256:4ae6a1e111642dbf724f635424dcaf5a5c8abbde49eac3f452f5323ffaa10232", size = 214420 },
+ { url = "https://files.pythonhosted.org/packages/7d/85/1477f23cf3b0476608ca987b4338f91439abb5b96564ac26b26d2cde38fd/zope_interface-8.4-cp312-cp312-win_arm64.whl", hash = "sha256:2e9e4aa33b76877af903d5532545e64d24ade0f6f80d9d1a31e6efcea76a60bc", size = 212992 },
+ { url = "https://files.pythonhosted.org/packages/8e/6a/a08c62bc1fa0e34fe7b8b401646cba4817427c716bfbef6cc88937cd327f/zope_interface-8.4-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:cd55965d715413038774aead54851bc3dbdd74a69f3ce30252182a94407b9905", size = 211924 },
+ { url = "https://files.pythonhosted.org/packages/50/30/2011f17e00ff078658bc317e1f7eccd7843fc1ce60695b665b0a52c45c1b/zope_interface-8.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0d88c1f106a4f06e074a3ada2d20f4a602e3f2871c4f55726ed5d91e94ec19b1", size = 211995 },
+ { url = "https://files.pythonhosted.org/packages/25/f3/a16fe884571cfa89271412dbb40def6d6865824428d1e14785a82795100c/zope_interface-8.4-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:36c575356732d59ffd3279ad67e302a6fe517e67db5b061b36b377ee0fa016c4", size = 264443 },
+ { url = "https://files.pythonhosted.org/packages/83/88/e08923fcd8a8c8704af05a90418b07cd897ac90865925b37d7ad8139adfa/zope_interface-8.4-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:29f09ec8bda65f7b30294328070070a2590b90f252f834ee0817cdb0e2c35f6a", size = 269626 },
+ { url = "https://files.pythonhosted.org/packages/27/67/96c94cd307f9946d0b0f03402a335f7aae7b4f0b129b5734cc56cc78cb65/zope_interface-8.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2bc388cebcb753d21eaf2a0481fd6f0ce6840a47300a40dcec0b56bac27d0f97", size = 269583 },
+ { url = "https://files.pythonhosted.org/packages/e2/d4/7e9fcc8bb0dba5d023b9fca92035d68c018457cc550e9d51746670b76a6b/zope_interface-8.4-cp313-cp313-win_amd64.whl", hash = "sha256:3e5866917ccb57d929e515a1136d729bd3fa4f367965fb16e38a4bc72cb05521", size = 214422 },
+ { url = "https://files.pythonhosted.org/packages/16/26/b0bcde302f6a4c155d047a8ab5cba1003363031919d6e8f3bcdc139c28a6/zope_interface-8.4-cp313-cp313-win_arm64.whl", hash = "sha256:f1f854bef8bc137519e4413bcc1322d55faad28b20b3ca39f7bec49d2f1b26df", size = 213029 },
+ { url = "https://files.pythonhosted.org/packages/f6/d5/ca60c8b404b303d9490e1417430a5198a77557dbeb17c1cb31616e432318/zope_interface-8.4-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:7cbb887fdbfaacb4c362dbb487033551646e28013ad5ffe72e96eb260003a1a1", size = 212012 },
+ { url = "https://files.pythonhosted.org/packages/83/64/6bb9f54250c817e24b39e986f173b6cd21ff658bec6c6cc0baad05d761e4/zope_interface-8.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a5638c6be715116d3453e6d099c299c6844d54810de7445ce116424e905ede06", size = 212071 },
+ { url = "https://files.pythonhosted.org/packages/c6/cf/42851262e102723058019dc7d0b48210b85a935f79ae32ce60ddccc2e8fb/zope_interface-8.4-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:b8147b40bfcd53803870a9519e0879ff066aeecc2fcff8295663c1b17fc38dc2", size = 266075 },
+ { url = "https://files.pythonhosted.org/packages/d2/a7/e48c79b836f6f0a2c219288e2ec343517f90e95c93de5435a8a23918bf20/zope_interface-8.4-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:049ba3c7b38cc400ae08e011617635706e0f442e1d075db1b015246fcbf6091e", size = 269127 },
+ { url = "https://files.pythonhosted.org/packages/6a/40/0e26f24d3a2f34f0de2cfeaab6458a865284d9d1fa317ab78913aa1f7322/zope_interface-8.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9c4ac009c2c8e43283842f80387c4d4b41bcbc293391c3b9ab71532ae1ccc301", size = 269446 },
+ { url = "https://files.pythonhosted.org/packages/91/d5/20310601450367fc35fa28b0544c98d0347b8cc25eaf106a2c4cc36841e1/zope_interface-8.4-cp314-cp314-win_amd64.whl", hash = "sha256:4713bf651ec36e7eea49d2ace4f0e89bec2b33a339674874b1121f2537edc62a", size = 215199 },
+ { url = "https://files.pythonhosted.org/packages/5b/00/0d22ce75126e31f81baa5889e2a40aad37c8e34d1220cf8b18d744f2b5d9/zope_interface-8.4-cp314-cp314-win_arm64.whl", hash = "sha256:d934497c4b72d5f528d2b5ebe9b8b5a7004b5877948ebd4ea00c2432fb27178f", size = 213178 },
+]