From b8a76cc10ecb9242f78df1485fbfdd2293d72813 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 09:52:45 +0100 Subject: [PATCH 01/34] chore: update metadata in the project TOML --- pyproject.toml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 168d507..59c3657 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,9 @@ build-backend = "setuptools.build_meta" name = "isaricanalytics" dynamic = ["version"] description = "Data analysis toolkit to support fast analysis of clinical data during emerging infectious disease outbreaks." + +# Contributors list includes VERTEX contributors of the code migrated from +# VERTEX (`getREDCapData`, `IsaricAnalytics`, `IsaricDraw`) authors = [ { name = "Tom Edinburgh", email = "tom.edinburgh@ndm.ox.ac.uk" }, { name = "Esteban Garcia-Gallo", email = "esteban.garcia@ndm.ox.ac.uk" }, @@ -15,9 +18,16 @@ authors = [ { name = "Luiz Raffaini", email = "lemraffaini@gmail.com" }, { name = "Sandeep Murthy", email = "sandeep.murthy@ndm.ox.ac.uk" } ] + +maintainers = [ + { name = "Alasdair Wilson", email = "alasdair.wilson@dtc.ox.ac.uk" }, + { name = "Sandeep Murthy", email = "sandeep.murthy@ndm.ox.ac.uk" } +] + readme = "README.md" keywords = [ "isaric", + "infectious-diseases", "disease-outbreaks", "clinical-data", "data-analysis", @@ -36,9 +46,13 @@ dependencies = [ ] [project.optional-dependencies] +pre-commit = [ + "pre-commit", +] + test = [ - "pytest==8.4.2", - "pytest-cov==7.0.0" + "pytest>=8.4.2", + "pytest-cov>=7.0.0" ] docs = [ From 15018cb191c94789fbc68fc98371c7f2cccee7bf Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 09:54:34 +0100 Subject: [PATCH 02/34] ci: rename test workflow to `test.yml` --- .github/workflows/{test-python-versions-coverage.yml => test.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{test-python-versions-coverage.yml => test.yml} (100%) diff --git a/.github/workflows/test-python-versions-coverage.yml b/.github/workflows/test.yml similarity index 100% rename from .github/workflows/test-python-versions-coverage.yml rename to .github/workflows/test.yml From 36a22610a5b8c0b6a34e1a36c6bfeb9796552aa7 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 10:03:23 +0100 Subject: [PATCH 03/34] ci: tidy up the pre-commit and test workflows --- .github/workflows/pre-commit.yml | 4 +-- .github/workflows/test.yml | 59 ++++++++++++++++---------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index c719208..f9c0b50 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -11,10 +11,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 with: python-version: "3.11" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 282b79d..26cf6e1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,51 +1,52 @@ -name: Tests (python versions) +name: Tests and Coverage -on: +"on": push: - branches: [main, dev] + branches: + - main pull_request: - branches: [main, dev] - workflow_dispatch: jobs: - - test: - name: Python tests and coverage + unit-test: runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - - strategy: - fail-fast: false - matrix: - python-version: ["3.11"] - # Note: Latest version is tested by os tests steps: - - uses: actions/checkout@v6 + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 with: - python-version: ${{ matrix.python-version }} + python-version: "3.11" - - name: Run tests + - name: Install project and unit test dependencies run: | - pip install pdm &&\ - pdm install -v -dG "test" --no-editable --no-self &&\ - pdm run -v python -m pytest --code-highlight=yes --color=yes --verbosity=3 -p pytest_cov --cov=isaricanalytics --cov-report=term-missing --cov-report=xml + python -m pip install --upgrade pip + pip install -e ".[test]" - - name: Upload coverage XML - uses: actions/upload-artifact@v4 + - name: Run pytest with coverage + env: + PYTEST_DISABLE_PLUGIN_AUTOLOAD: "1" + run: | + python -m pytest \ + --code-highlight=yes \ + --color=yes \ + --verbosity=3 \ + -p pytest_cov \ + --cov=isaricanalytics \ + --cov-report=term-missing \ + --cov-report=xml + + - name: Upload coverage.xml artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f with: name: coverage-xml path: coverage.xml if-no-files-found: error - - name: Upload coverage report to Codecov + - name: Upload coverage report to Codecov (best effort) continue-on-error: true - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 with: files: ./coverage.xml token: ${{ secrets.CODECOV_TOKEN }} From 60412c073d03c56140e9ded46f45fdd4be24b55b Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 10:36:44 +0100 Subject: [PATCH 04/34] ci: add build workflow for building of local package artifacts and a simple import test of the wheel installation --- .github/workflows/build.yml | 23 +++++++++++++++++++++++ pyproject.toml | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..2dcdf51 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,23 @@ +name: build + +on: + push: + branches: [main] + pull_request: + +jobs: + pre-commit: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + + - name: Setup PDM + uses: pdm-project/setup-pdm@94a823180e06fcde4ad29308721954a521c96ed0 + + - name: Build artifacts + run: | + pdm build -v + pdm add ./dist/isaricanalytics*.whl + python -c "import isaricanalytics; print(isaricanalytics.__version__)" diff --git a/pyproject.toml b/pyproject.toml index 59c3657..ee82007 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,8 +20,8 @@ authors = [ ] maintainers = [ + { name = "Sandeep Murthy", email = "sandeep.murthy@ndm.ox.ac.uk" }, { name = "Alasdair Wilson", email = "alasdair.wilson@dtc.ox.ac.uk" }, - { name = "Sandeep Murthy", email = "sandeep.murthy@ndm.ox.ac.uk" } ] readme = "README.md" From ace567d6532d8da2b3cca9bf803aaa12aecf9a1f Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 10:38:55 +0100 Subject: [PATCH 05/34] chore(deps): refresh pylock TOML --- pylock.toml | 292 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 206 insertions(+), 86 deletions(-) diff --git a/pylock.toml b/pylock.toml index 93292cd..d2f0f1d 100644 --- a/pylock.toml +++ b/pylock.toml @@ -3,7 +3,7 @@ requires-python = ">=3.11" environments = [ "python_version >= \"3.11\"", ] -extras = ["docs", "test"] +extras = ["docs", "pre-commit", "test"] dependency-groups = ["default"] default-groups = ["default"] created-by = "pdm" @@ -265,6 +265,19 @@ dependencies = [ "pycparser; implementation_name != \"PyPy\"", ] +[[packages]] +name = "cfgv" +version = "3.5.0" +requires-python = ">=3.10" +sdist = {name = "cfgv-3.5.0.tar.gz", url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hashes = {sha256 = "d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132"}} +wheels = [ + {name = "cfgv-3.5.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl",hashes = {sha256 = "a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0"}}, +] +marker = "\"pre-commit\" in extras" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "charset-normalizer" version = "3.4.7" @@ -668,6 +681,18 @@ marker = "python_version >= \"3.11\" and \"docs\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "distlib" +version = "0.4.0" +sdist = {name = "distlib-0.4.0.tar.gz", url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hashes = {sha256 = "feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}} +wheels = [ + {name = "distlib-0.4.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl",hashes = {sha256 = "9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}}, +] +marker = "\"pre-commit\" in extras" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "docutils" version = "0.22.4" @@ -706,6 +731,19 @@ marker = "\"docs\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "filelock" +version = "3.28.0" +requires-python = ">=3.10" +sdist = {name = "filelock-3.28.0.tar.gz", url = "https://files.pythonhosted.org/packages/d6/17/6e8890271880903e3538660a21d63a6c1fea969ac71d0d6b608b78727fa9/filelock-3.28.0.tar.gz", hashes = {sha256 = "4ed1010aae813c4ee8d9c660e4792475ee60c4a0ba76073ceaf862bd317e3ca6"}} +wheels = [ + {name = "filelock-3.28.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/3b/21/2f728888c45033d34a417bfcd248ea2564c9e08ab1bfd301377cf05d5586/filelock-3.28.0-py3-none-any.whl",hashes = {sha256 = "de9af6712788e7171df1b28b15eba2446c69721433fa427a9bee07b17820a9db"}}, +] +marker = "\"pre-commit\" in extras" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "fonttools" version = "4.62.1" @@ -813,6 +851,19 @@ marker = "\"docs\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "identify" +version = "2.6.18" +requires-python = ">=3.10" +sdist = {name = "identify-2.6.18.tar.gz", url = "https://files.pythonhosted.org/packages/46/c4/7fb4db12296cdb11893d61c92048fe617ee853f8523b9b296ac03b43757e/identify-2.6.18.tar.gz", hashes = {sha256 = "873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd"}} +wheels = [ + {name = "identify-2.6.18-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl",hashes = {sha256 = "8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737"}}, +] +marker = "\"pre-commit\" in extras" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "idna" version = "3.11" @@ -1608,6 +1659,19 @@ marker = "\"docs\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "nodeenv" +version = "1.10.0" +requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +sdist = {name = "nodeenv-1.10.0.tar.gz", url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hashes = {sha256 = "996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb"}} +wheels = [ + {name = "nodeenv-1.10.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl",hashes = {sha256 = "5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827"}}, +] +marker = "\"pre-commit\" in extras" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "numpy" version = "1.26.4" @@ -1654,11 +1718,11 @@ dependencies = [ [[packages]] name = "packaging" -version = "26.0" +version = "26.1" requires-python = ">=3.8" -sdist = {name = "packaging-26.0.tar.gz", url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hashes = {sha256 = "00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}} +sdist = {name = "packaging-26.1.tar.gz", url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hashes = {sha256 = "f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de"}} wheels = [ - {name = "packaging-26.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl",hashes = {sha256 = "b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}}, + {name = "packaging-26.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl",hashes = {sha256 = "5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f"}}, ] marker = "\"default\" in dependency_groups or \"docs\" in extras or \"test\" in extras" @@ -1852,7 +1916,7 @@ sdist = {name = "platformdirs-4.9.6.tar.gz", url = "https://files.pythonhosted.o wheels = [ {name = "platformdirs-4.9.6-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl",hashes = {sha256 = "e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917"}}, ] -marker = "\"docs\" in extras" +marker = "\"docs\" in extras or \"pre-commit\" in extras" [packages.tool.pdm] dependencies = [] @@ -1886,6 +1950,25 @@ marker = "\"test\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "pre-commit" +version = "4.5.1" +requires-python = ">=3.10" +sdist = {name = "pre_commit-4.5.1.tar.gz", url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hashes = {sha256 = "eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61"}} +wheels = [ + {name = "pre_commit-4.5.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl",hashes = {sha256 = "3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77"}}, +] +marker = "\"pre-commit\" in extras" + +[packages.tool.pdm] +dependencies = [ + "cfgv>=2.0.0", + "identify>=1.0.0", + "nodeenv>=0.11.1", + "pyyaml>=5.1", + "virtualenv>=20.10.0", +] + [[packages]] name = "prompt-toolkit" version = "3.0.52" @@ -2023,11 +2106,11 @@ dependencies = [] [[packages]] name = "pytest" -version = "8.4.2" -requires-python = ">=3.9" -sdist = {name = "pytest-8.4.2.tar.gz", url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hashes = {sha256 = "86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"}} +version = "9.0.3" +requires-python = ">=3.10" +sdist = {name = "pytest-9.0.3.tar.gz", url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hashes = {sha256 = "b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}} wheels = [ - {name = "pytest-8.4.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl",hashes = {sha256 = "872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"}}, + {name = "pytest-9.0.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl",hashes = {sha256 = "2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}}, ] marker = "\"test\" in extras" @@ -2035,8 +2118,8 @@ marker = "\"test\" in extras" dependencies = [ "colorama>=0.4; sys_platform == \"win32\"", "exceptiongroup>=1; python_version < \"3.11\"", - "iniconfig>=1", - "packaging>=20", + "iniconfig>=1.0.1", + "packaging>=22", "pluggy<2,>=1.5", "pygments>=2.7.2", "tomli>=1; python_version < \"3.11\"", @@ -2044,11 +2127,11 @@ dependencies = [ [[packages]] name = "pytest-cov" -version = "7.0.0" +version = "7.1.0" requires-python = ">=3.9" -sdist = {name = "pytest_cov-7.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hashes = {sha256 = "33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1"}} +sdist = {name = "pytest_cov-7.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hashes = {sha256 = "30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2"}} wheels = [ - {name = "pytest_cov-7.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl",hashes = {sha256 = "3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861"}}, + {name = "pytest_cov-7.1.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl",hashes = {sha256 = "a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678"}}, ] marker = "\"test\" in extras" @@ -2074,6 +2157,22 @@ dependencies = [ "six>=1.5", ] +[[packages]] +name = "python-discovery" +version = "1.2.2" +requires-python = ">=3.8" +sdist = {name = "python_discovery-1.2.2.tar.gz", url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hashes = {sha256 = "876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb"}} +wheels = [ + {name = "python_discovery-1.2.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl",hashes = {sha256 = "e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a"}}, +] +marker = "\"pre-commit\" in extras" + +[packages.tool.pdm] +dependencies = [ + "filelock>=3.15.4", + "platformdirs<5,>=4.3.6", +] + [[packages]] name = "pytz" version = "2026.1.post1" @@ -2140,7 +2239,7 @@ wheels = [ {name = "pyyaml-6.0.3-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl",hashes = {sha256 = "8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}}, {name = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl",hashes = {sha256 = "9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}}, ] -marker = "\"docs\" in extras" +marker = "\"docs\" in extras or \"pre-commit\" in extras" [packages.tool.pdm] dependencies = [] @@ -2872,6 +2971,27 @@ dependencies = [ "typing-extensions>=4.0; python_version < \"3.11\"", ] +[[packages]] +name = "virtualenv" +version = "21.2.4" +requires-python = ">=3.8" +sdist = {name = "virtualenv-21.2.4.tar.gz", url = "https://files.pythonhosted.org/packages/0c/98/3a7e644e19cb26133488caff231be390579860bbbb3da35913c49a1d0a46/virtualenv-21.2.4.tar.gz", hashes = {sha256 = "b294ef68192638004d72524ce7ef303e9d0cf5a44c95ce2e54a7500a6381cada"}} +wheels = [ + {name = "virtualenv-21.2.4-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/27/8d/edd0bd910ff803c308ee9a6b7778621af0d10252219ad9f19ef4d4982a61/virtualenv-21.2.4-py3-none-any.whl",hashes = {sha256 = "29d21e941795206138d0f22f4e45ff7050e5da6c6472299fb7103318763861ac"}}, +] +marker = "\"pre-commit\" in extras" + +[packages.tool.pdm] +dependencies = [ + "distlib<1,>=0.3.7", + "filelock<4,>=3.24.2; python_version >= \"3.10\"", + "filelock<=3.19.1,>=3.16.1; python_version < \"3.10\"", + "importlib-metadata>=6.6; python_version < \"3.8\"", + "platformdirs<5,>=3.9.1", + "python-discovery>=1.2.2", + "typing-extensions>=4.13.2; python_version < \"3.11\"", +] + [[packages]] name = "watchfiles" version = "1.1.1" @@ -3065,77 +3185,77 @@ dependencies = [] [[packages]] name = "wrapt" -version = "2.2.0rc3" +version = "2.2.0rc10" requires-python = ">=3.9" -sdist = {name = "wrapt-2.2.0rc3.tar.gz", url = "https://files.pythonhosted.org/packages/38/07/09130d19f55b839f8e9915600426b573f2c569c727af950b924b8b152c1c/wrapt-2.2.0rc3.tar.gz", hashes = {sha256 = "ed13b1a7fe884c566c5f43005275781995d0cf7df563893968a187c881755522"}} -wheels = [ - {name = "wrapt-2.2.0rc3-cp314-cp314-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/0c/57/4f27842a4d8bf393e1466efed0072f78aaad00e5201cc8f514b9702ac629/wrapt-2.2.0rc3-cp314-cp314-macosx_10_15_x86_64.whl",hashes = {sha256 = "8d898c0004cd6ab95b3e00059ffe3ede6925fcaf7e2a9dcdb30eef3ddcc78372"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/75/15/b0a797ecfe80d1161fb7ea22ffd46bc0026ce0ff403bed47553c7fad3332/wrapt-2.2.0rc3-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "65b03d053ca24fa3ea5ed8d989133793754750d72ab4f4dc43f9d75f9149265c"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/67/7a/e8d1b5bac41c453b52756af1d4d07494216259f975e0ccfc9bfed4f596ff/wrapt-2.2.0rc3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "990c5de27e6ef54d81554e44d4b4b46d7f9da9f336a8a94c25131c52f29477b3"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/dd/e3/1dc8e456209feae8ff33e92db1cbc922e9575b0fe8d273a4237a313e6a4d/wrapt-2.2.0rc3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "91e8534d7400faca16ad963362c65c4b652c04a4c466dde3731711623ff37208"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/2e/b0/8b77a11aaf4fa137f832ed0c434dfe82945dfa32cabb77e32c808a04a990/wrapt-2.2.0rc3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "c9ce8df6846080e5b98d692f44539fa0a55c53cd5ce155d1e0a5b2602fff3c3f"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7e/cc/9ad5d4f831841bc584dca392b9e774f65b01e5a9765df30ab2d1213e4f27/wrapt-2.2.0rc3-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "df3215d229ef749b9f22583f65492babf665da43e69d032be5002bdb49ea1658"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/44/53/f39ecd0bcedf33b390b8ea9b57c0d71a447efa5d92d47537c3cedfb7d7df/wrapt-2.2.0rc3-cp314-cp314-musllinux_1_2_riscv64.whl",hashes = {sha256 = "cc44d18cce2978e495ed966191f286069c6b0b71c70023e3e40d41815ff23657"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/ec/69/de9fc0f01064c97a6adc6dec5c064862a9c249d4fe852e739c047d10e072/wrapt-2.2.0rc3-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "dd21c9d4bdc9e2415898bf4fa84d572099e6af3d973cda3d1ad8ec4bcf02ef07"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/77/21/2ee00b66a703b3f4e03afa1ee896808f7c93870d55b29bf92e1fa8132880/wrapt-2.2.0rc3-cp314-cp314-win32.whl",hashes = {sha256 = "0de1071e6236945fec242cb3dcfc126df4cd97e9dc2cbab073958e43cb92689b"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f1/ba/95c28d7df311bc7c0bbbf6a2ddd27e49cecb4116fb608ffef254008dc364/wrapt-2.2.0rc3-cp314-cp314-win_amd64.whl",hashes = {sha256 = "aa22a1c80cfedc34c4b2e008a16ed54135540346ae60a498f669fac254f07d70"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/38/ec/c9ea13f1d64b423cd5b7796285969f8d2302b4bfcbb9230a48db72fe26a9/wrapt-2.2.0rc3-cp314-cp314-win_arm64.whl",hashes = {sha256 = "60a5aa6ef766369732fdf4d7f9341de02bb45bfc65564c162719a5f21ae77106"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/74/d609a43264122759a806a1c13dc708905f68109f369902322c6720518cf5/wrapt-2.2.0rc3-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "a8e215eeaec45a5272cff9870cf3c02d9642b2baf0d05f435374e1eb113e37c7"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/5f/b6/b409700e417478c18ced9ecdcdb9a4151903cb4fc46423deb13a2ecfcc14/wrapt-2.2.0rc3-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "d0404ee67d0bf24f69ef741222e055e78a1f29d8dc25ad11b515a1e2d5a2c082"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/f6/32/6a5e70ba41fbd308b1018366268e1834853acab876a3a15ff2b3be1a410e/wrapt-2.2.0rc3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "d9fe7df6f84287b2849fbb5ff3f6d82b5e90a9d77f25ef0c179cd5304e663d31"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/7d/2e/228a38c264be3b60eec508352f6beb2adce9a5528054a2c71da9115ee1ff/wrapt-2.2.0rc3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "65f6565e2dc14e897bc1c3c7b40dd705443e8ab1dc1119cff2163487a0354d2e"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/dd/ea/96ce6f797a3a6b06a7d4b2633caac8e16c7425a1b6faa13d7a7062e3e026/wrapt-2.2.0rc3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "d234a031d0cd30a58a58c54a2fc62e8c0ca4c8c08db79822c9823c4669ececab"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/86/28/7bc00b27e50de403e2d64a1698b1a0ec6ad1aabc60ec97a0c40dbe2add54/wrapt-2.2.0rc3-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c57c2357ba8edb5731bc627636ae44fe8282132ed41fb3240dd8befb50990324"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/fe/ac/0e176d41ad099d9ce9d8abb0783c206729771b634e2d8d2ae8c9137d4658/wrapt-2.2.0rc3-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "f4dc124f1f893711a00fc953090afcbe2ff1ef37fa3c6bccf90556c49f0c6198"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/52/c7/e3c9dae54305a1161e917912f8b65280eee716fde468384e91649c5fbaba/wrapt-2.2.0rc3-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "c6aab1869ee1dbfcb19be9276f2464673c3f4bb3ee91ae32eb3726e51ffe5ebd"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/36/d4/05117de84485eaa26266ae8bcff33e3b2efd9d4c82298e30b01f4d8a91ba/wrapt-2.2.0rc3-cp314-cp314t-win32.whl",hashes = {sha256 = "db1e3a3884cc04cba171ef895ba9e1491fd21e45faaea86ad9fe3c7fee7fcf30"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/0f/92/f2db8bdff5fa952b7b9ea443ee233dbbe03137f30e27ca5a34bfaa1206aa/wrapt-2.2.0rc3-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "7ac0b3a0e13f8eedeb557304d5dfd4ba2d80408e9b595bc4c6e8ea385e3483a8"}}, - {name = "wrapt-2.2.0rc3-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ec/9f/1dc14a35e1d0e477dc74ed0ad95da8250b401803bb6a41529666c6d0988d/wrapt-2.2.0rc3-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "f5f679a3a35dfe744f5a878d97e018e6051c3dafc55ccc8ed19f058e35896484"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/05/30/26e0eca25e039803ec1881ce167a273475046ae60171cb96448db616df8a/wrapt-2.2.0rc3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "fd0d18c4cf1d807d1acead5a58f356c46b31b3caecccd92065ae58c7f043fbca"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/83/e2/93c16932428f58023cdcaa7eb6653a20d8fe4e24de668c98afadcdb1e234/wrapt-2.2.0rc3-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "7526e5fc731f4e1fefb617111f6071b2d4360c8fad19e937b2af6b1cb87c5653"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/26/10/3d92539ee2e475333aa62f0bb22fd521335ee3c52f293454a37510ce32ca/wrapt-2.2.0rc3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "16f4eaf6112e10c6a77fac62763b7ea62db2b36c87ae5782e14a496d8c242d18"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e7/29/a627cc823dac52b5448339a82664f0d3a7405f452e2d49ed0ce9da07fb5a/wrapt-2.2.0rc3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "9c5665cdc7667579db641b200869eb81bcdd70f05e789799135c668b9fa6ab86"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/c4/3f/5ed1cf8228154dd80db5847239bc8f52cd3cb7135c5c558c891212ea9cb0/wrapt-2.2.0rc3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "0eb8c176ba23ae1b75cd94851441737b9c1d5761d51912443436ae2ceb3490de"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/09/39/21abf3414bd51052edc24744d04c887d6dd4fa75746d860ae2fa001348b7/wrapt-2.2.0rc3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "0174a7874b64bdd2e1f5aeb90b95bd35af2a70e9d2b4539abc12bb588ecd7e51"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/1f/35/a0be5b943e9a948839ed249d8e9f5fad87836c7d987c32bd01ff4be99c22/wrapt-2.2.0rc3-cp313-cp313-musllinux_1_2_riscv64.whl",hashes = {sha256 = "0d25acd07566df8e00c7ae87175ff74b1e20864c19afd943e51a9b9bed3f47dc"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/3b/14/83d268fdc932c204e399d5966c6db185f96458cb07096aef16bf809a922a/wrapt-2.2.0rc3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "eb7f17a5d1438f7df4176b2ba9c0f157df564726385cb5b0778d815bf4b637c2"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/03/eb/8ffb3fa781c0d407cea764a7e4ab69996494952337507005195cdcfe0c3d/wrapt-2.2.0rc3-cp313-cp313-win32.whl",hashes = {sha256 = "06df2cd319933ceba8e3274e95f34c7bee8496e9c73de74189a8dc57a3769af2"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a9/20/253f33f0879c0c4e1945b71485e60d79f9c4d32ddfa25e866d8b97cac0fe/wrapt-2.2.0rc3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "093c5f7882a55f08d26f491d97570c3bdc2cb551bc396971099df610c76aa517"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/d2/90/9fb671613be4bb1ebcde40c5d9b99a3adc10479c4955f5e68d0e251821e5/wrapt-2.2.0rc3-cp313-cp313-win_arm64.whl",hashes = {sha256 = "2de3813a0c45e72d27443ee72bad95a080c7964d7f0861e865641547c014429b"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/78/cb/6b25dbb0e249e2e471a0c0eebc55b1879dfdf70b5ad394533250663bd4e7/wrapt-2.2.0rc3-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "9991d25aac1bd21f5c79c599aa50ed2f5dfcb2283e270bf2f6989a89a587e411"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/16/c2/0be1965f30e8979c950b7a7d1f738626e09301636cdf136f673496f0f523/wrapt-2.2.0rc3-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "9aeef0adae70a896135f6d3f476d66a2e513c1e9aea79ede7ae5e3132e84af13"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/a5/6f/0ab718d4cfa900d023e77795ded8d9b6e73e413e6520eeb09b17c57eecdb/wrapt-2.2.0rc3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "664f7a6afd694fb7f9aa6b6f1e172a0f63467a4e933cc6db500b222cad870844"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/6d/99/f8660f1884ce78b92f35ec49a790dc43b2207ff97f285be5ffa2a9f64980/wrapt-2.2.0rc3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "e0c28c7dda874d1380a2e185528a9e7177879d24e49661a2c1e8f154c33613e4"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/4c/af/a62320bab40b41df3e1b80ca7d1f0d8b8b6da2268d064ca160f0143e95a9/wrapt-2.2.0rc3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "d76fcc7e8b903e4cf461853a5e924b7f9a563595eb9048d7fa1fd6dbc9484fe6"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/44/e1/c35ad67f1ed93e20d4e9f3067a82314eaa31cb4b7596b0b27fa39061a186/wrapt-2.2.0rc3-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "512f86d21d9ffb5cfe0392f429c6184dabc2878ab19f0fc9b4bf745620ed8b0a"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/be/ea/25bdf71827a8aa98cd713cb6da3463c79e2e5c55ce07316393d43b9c7eb2/wrapt-2.2.0rc3-cp313-cp313t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "c90c7b8f5947f062bbf8f01110c41250d8e0aec89d0df977ebdcf29f143afaa4"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/de/25/80b5ae1b93811fb61160db9aca676a2634967e895227ba9ce33e7f9a35da/wrapt-2.2.0rc3-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "e09a1108f4d76548d1e3366435c762160e404661570276ca18f478b9f729eb8b"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/b4/77/e65b4361b652f11392a20be805ea5689e8167370e6874ac472b3cefaf068/wrapt-2.2.0rc3-cp313-cp313t-win32.whl",hashes = {sha256 = "b5e6b0efcba38ce327ff8547fb7d5c93170c6979692f758eecd7fb096691c22b"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d6/8d/9138d6401b7150c5f014446897adde112fbdbb03c2bf31b7609a5ec9f9e5/wrapt-2.2.0rc3-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "b1fa573979b545558f419ce1489b34024aeeab64c0e2e1648fd055ebf2b2f37e"}}, - {name = "wrapt-2.2.0rc3-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/6e/e7/50f4e9d187d6c1cac8c29e0c635cad9763f49eefc6da5da68ce155e26ef4/wrapt-2.2.0rc3-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "bfd50e6dd9982a624ce0f4f21ebd4e8fa37e3664aba76eca321471041bd63b28"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/f0/f1/3cd2112e119e3ea82947e1ab431299c239ef7cde58cc97884c9fecf67fbc/wrapt-2.2.0rc3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "d303a284255346a3603741e6b1fcb46864e3f27b211ce7cac20af0aa569f79e8"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/81/35/ab9f40d400ed0a2d39ed83e95f22242e0a29f5ce1de72a09792973f79a3f/wrapt-2.2.0rc3-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "f44139c54780b15bf9ad1a0e14a5d421fc5658f0f4bc3c3e50ed0960943b8aa1"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/5e/ba/f570b1d0c02ec19f4bbf39a8154dac676b484cc6f7f8cde42f333eb3bd6e/wrapt-2.2.0rc3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "959ee73202b3780e1ff926314e81702c2231eae788d6316520b841a4f261486f"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ce/6f/506eff0fdef6cb8bdb78ef3e29bd8984e467eb046a3d1190d9e15162fa71/wrapt-2.2.0rc3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "405fa7fc28692799355faacf5ba1aa25bd37583ac8d29fbe10f39b494fe334ed"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/1a/38/bd221cefa1141836a07c9df21625359ddde7fc882342fc01c060e5f13947/wrapt-2.2.0rc3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "f07d07f0f3d54fc2fa5f7a7364a123e607d41f87738636c622460faee6d384cb"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/e5/71/31794f781f738d131121a80fdbe62497cd5de8c9dc80c95e036b220a968f/wrapt-2.2.0rc3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "402440b7714f6da36047a9f18282927c98c07158aa49c68f62a670e37e9b96c7"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/cd/56/eb662e32a91e25ccd76f83da167cde4b3d2d9c05602f277eec059f7217b6/wrapt-2.2.0rc3-cp312-cp312-musllinux_1_2_riscv64.whl",hashes = {sha256 = "3bd7c1dd9863a76e611ce95b4d3cf1c665de2e4c8f68430ba9990b8cba224e85"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/0d/5f/5e5769af8a73bce03afcab236aa3fc38522b09f74cdc1433afac6cde2f76/wrapt-2.2.0rc3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ce60034d4cc4ae2c61cdc63284963330efbb5a62cd674e19b0478fc0969a66f9"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/e1/53/26f579e9eeaa57b90716a5830868ab185506a53fd4572c221a4a188f9c4e/wrapt-2.2.0rc3-cp312-cp312-win32.whl",hashes = {sha256 = "dfad8b093a8e63db4ab1aab6cdd885d75171e0c75dcac1f9d66acdd4a918b76d"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/4a/4a/edcfe15a929979efc3937cca26ce459b5db09abfa9e93eb79f2597c9c383/wrapt-2.2.0rc3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "248591aeff15ba463f7888fcf3ce1b012508600d02f208ee2b6486ac270a5951"}}, - {name = "wrapt-2.2.0rc3-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/1a/de/d599cf92667e6d2b5985d576e2eb3c93c7ddf49d7f9e3bf4799768af6538/wrapt-2.2.0rc3-cp312-cp312-win_arm64.whl",hashes = {sha256 = "3204b133a0f83728546b0a4df0917e26abc96c59ee91a906fdcd65bd2ccb8cae"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/88/db/c114873d0b28de13e9ecfc544fc28931d59c469b1217a08a8b5ad12fec39/wrapt-2.2.0rc3-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "cf6c20d8e347b513d3843347b41b9f9a1b3a38877ebd124980d64e02841aff55"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d7/f8/1657979ab5e0ef54c7cced88c05f05dad38340835ef44bb2842f26c271e3/wrapt-2.2.0rc3-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "0164ac2c37658f0a219db35c24dc0c20fe5f1a02afc34c5c75818181d489842e"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/e8/b6/6861418529338eba2b52034513916e45bb6170da23e295dd9ea19dfa45ba/wrapt-2.2.0rc3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "5e9df9d7b66ea193265970d55d45869ef65d8711b9469ee588120444342bc580"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e5/43/0d4d1efa5cd248e072155205962dee8c75b1b85e4fb6ec0ba80381332dc2/wrapt-2.2.0rc3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "b2b5c1a53ac1beb52fb02274edebf3114533715820cc25c41640329e6250f0a6"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/de/25/84ef175fbf36b06624aa2853be5ecbf5083530784ac8e3bb3a3b164ec708/wrapt-2.2.0rc3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "e11f2e170d9eddbf213627503af9178798ef9fc819e78c1e8d18927325418c26"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/1f/32/097debf07223beceb8391258ccc93d0109f39e0369e28659aa330093a1e4/wrapt-2.2.0rc3-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "0711a9985bf6340ec8d9314ed281629e281238873160803908574483fb2c1919"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/a9/c6/036dde151c8cbfde3a8908300c938149a022a1cd58ba008e696a45daeb16/wrapt-2.2.0rc3-cp311-cp311-musllinux_1_2_riscv64.whl",hashes = {sha256 = "bacee6c2f4df4920fa4728841a79c1021b9dbe623c35be4f7505ca09457cda61"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/5c/40/dd6d2b6fb9d05c2fdc727a6f48c15596a4c54f5eadc5f284b92d557224eb/wrapt-2.2.0rc3-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "97701673217c449df62b96d8a61db03a59c5719dd1f0d5367b16f9cb154581d6"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/1a/5c/fb253482098e2c02558b818c8a38f11111734ec698250ca2dc5fcfe0e6b4/wrapt-2.2.0rc3-cp311-cp311-win32.whl",hashes = {sha256 = "9805e432eebd88420f7e874ead4d46e0ae99cb6993633dda8c1da961d67a6068"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/fc/1e/82be79da7e232055a6fce9d55ef56e0fadbc62572c9a28a2d0cd9c527de8/wrapt-2.2.0rc3-cp311-cp311-win_amd64.whl",hashes = {sha256 = "46fb5a9b3b5dcd886f1321102dc00a5baee959882ff37576ebc5b0f6b829e1b5"}}, - {name = "wrapt-2.2.0rc3-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ff/cd/9331f2f077c64cd35e893dc10682d55c369c2cbba3c6e1c02e453d712710/wrapt-2.2.0rc3-cp311-cp311-win_arm64.whl",hashes = {sha256 = "736480d112c84531fa8ce58ae87184cec095ca875749da4041c5ee11e497e9dc"}}, - {name = "wrapt-2.2.0rc3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/7d/3a/9492c966cee45f466c47f67d61b9df6f3240ced9ec97c47ad1c87f758b02/wrapt-2.2.0rc3-py3-none-any.whl",hashes = {sha256 = "00f85862d333af74ce062cd785c39dabaa1bbe7c6fc27c9872b398261eeea2be"}}, +sdist = {name = "wrapt-2.2.0rc10.tar.gz", url = "https://files.pythonhosted.org/packages/40/13/fd5226e965a6c31ab6b9a6c703e2cf29a0ffab8fa3785dd9cabe371d4f68/wrapt-2.2.0rc10.tar.gz", hashes = {sha256 = "654334906fbec684efa5fbd3a0c8753f128a9db2134ebed87d5b10768b799a1a"}} +wheels = [ + {name = "wrapt-2.2.0rc10-cp314-cp314-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/5f/93/86b3fa8be60b03f9b06af060ed01fb23b881f9349f2f64423b36f0bcb6b5/wrapt-2.2.0rc10-cp314-cp314-macosx_10_15_x86_64.whl",hashes = {sha256 = "8f81ac6aa1183d158cb6ce3f0cf8e67edd601af99a5c0c5729bbb188a548eccb"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/95/61/a031db81126842c222a52a20b7f44ae7dcb5d29604a11dc82fa9702a447c/wrapt-2.2.0rc10-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "fa2588aaec955021caa7f6fe526a3db8418dd9197737c036f1402836982dbd31"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/8e/c1/07b15a0298060d3b749e99724e7a23a8ee30d69b846c84333d95e69135d5/wrapt-2.2.0rc10-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "0264dc31acc543e4b186ce41ae8374d40384e97488d6d616b4765839008ec4ab"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/60/78/e88bb8f79d460585e1aeb3469cd2237c51adc5a60bbcff73427eaef1d9c1/wrapt-2.2.0rc10-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "81282653edcfcaa8b05f35692daccf15e1d47690cd1d9538d5f6937b9cb3fd0b"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/e8/d2/36c7abda986d21267ac43205d68f8ad25d3d5a16ac4492696265224fce2d/wrapt-2.2.0rc10-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "2be486e8cf121327eb6df10c906352218136fd54c6ce7ea5a4e35e0af1a1081c"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/44/55/6d6f83545cd3a50384e4868786a6a140a1fc114e3310f3cb72db6343e3b1/wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "69f304d6ab0fcf74120e85d44f416f11258a72f410df4570be9342c01823224a"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/ac/ec/ef72311b88a758e01ab471e368912e31c32cb2a1c674bc25553544a172e6/wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_riscv64.whl",hashes = {sha256 = "c2316cfe68080cacdaef29f1da9b61afdc3c3d6934c9163aa4110523b2e1528c"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/61/4f/16ccb49177f7e73808c2ac27f87a5373226cc330cd7a356e7f82ed72d4da/wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "d2873fc2e3b33170ef4e674e9d1e94637a8d104a6161234ad0dbf1918a5bc5e5"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/f7/14/43d7969a06d97091cdc418a67df86d1d29d466f8903a933cd3851e38ab5a/wrapt-2.2.0rc10-cp314-cp314-win32.whl",hashes = {sha256 = "97c123982cb4abb9799c543faedc9cae4a7f6695cca013d4d8fa245e5a0b5e5f"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/2d/fb/effded00ec679fdeefc060b7119c0d02c0a420e3a230ea02cc2e088a725b/wrapt-2.2.0rc10-cp314-cp314-win_amd64.whl",hashes = {sha256 = "800d0da73858e61ff32e30ed12aeeec2d51c816bedf3619c05f78905d09956cd"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/88/55/5ff81420fdddf3574458e9d1beb477c3bd860b2c9c02b0ba49f22bce9d11/wrapt-2.2.0rc10-cp314-cp314-win_arm64.whl",hashes = {sha256 = "579b96c9850ac93ac7ab964f37045e36657e6348c4c14181f7792c9f38a30e80"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/4b/31/5fabfc6749f67d7f4b9f31e976879987a2cc5f18247c55490621bda7654b/wrapt-2.2.0rc10-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "974138642610c4bb7c24edc1b8304a9c2eae53af42b678014a8414113aa5d166"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/69/de/679d843b0247db8cce17c32d1d7cf718b0cd1812c99e0cada9dd7150a37f/wrapt-2.2.0rc10-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "4ae962f92725e3e4f7d6711b56d53f525463c7cc0256a571fdc5115eae46641d"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/8e/d8/25400020518cef71544f02397c3e1282ebac11ffd68ffc9aa7797b0249a3/wrapt-2.2.0rc10-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "717d2d3da21ddb8a74d83e7c453b8b0a498883785e930c3a479a2a20f2e09746"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/01/b6/8b2788f70827ab17aa13ad2194f493fe69f203adea240567ca4e273a50b0/wrapt-2.2.0rc10-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "1ad1ffbb60ead11d9e014de1674b4a7922c1319a390a70812255c83f88d41782"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/ff/04/9675990b320e532a8c3f71ab1a881e416ae3d71c63ff707e5d853d9d2b4c/wrapt-2.2.0rc10-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "30b29f51d4e1ea12bd9ed8d1243050b7bec0bc012bc2d61bd8597eecf2b64772"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ed/54/7e42c0e51b6191588a14a7805129f0ded9f4e90da1cbd53b708e80096029/wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "476587d75363ff7b789e0c778300154c0a8cf741774f3ed953fbd6bc44d88d18"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/05/e0/1cca6bf14783228e1d6f0904fada908e2ce392ed789fa570a8f24d651eea/wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "6db5b52799a3be5da639fdbc5a58669b033d6f696e58284216b229cb1779c144"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/cd/d9/2ced8e598e455264d6c97261896f2415383789f79ec0117f5c07ea33653f/wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "7941ab8fc6460d2891a85dabcfaa1b2fb047c60c713f8ae87b455ecc9d2d75b2"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/52/32/b48789ff0ef224136bf1d4d26cb19b88fb963dd067e73a285eaa4fe8c7a4/wrapt-2.2.0rc10-cp314-cp314t-win32.whl",hashes = {sha256 = "a0c26e62f8edaff22b1284815123c851eded22f56c8ecdfef9c29d6571df8780"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/00/42/06dd084432d2137e104c1536616769d3fd19bcfe3e2744b7bfc5153bef45/wrapt-2.2.0rc10-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "ec65618456363f1e0530d362bd9ea48541494aff576370d9e7523977d67e37e8"}}, + {name = "wrapt-2.2.0rc10-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ca/23/46d71ac1f8797cf7197bcb034df656ed64d77c1ba04b688aae4187d3c7dc/wrapt-2.2.0rc10-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "37e1e4a4c6900ef832069f648e4c0c897058fa333000ddd73de91c42f05ba8b5"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/0a/a1/629b4fbb4e372206aa1587a5dbbbc737f50d6e17f8dec10f4505b4a18c59/wrapt-2.2.0rc10-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "8d174cfd2234f9695060693b05d0cdf4a29c7fc58a3896805de1f06df5e17678"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/91/19/701c35fb8cf379872065c4a113f1c55c71150a1b8535bd87afbde8153bf1/wrapt-2.2.0rc10-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "eef11c5defad6aaed70b1a332948b02d3eceb14e9cc72c485c97b3007aff2a89"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/e8/d4/c39c269e08d61cf2d2006646c876bd756ccaa648277f32ae55888bf6b187/wrapt-2.2.0rc10-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "64ab66a4f93c54fb11deff60470ca90ca95dfabd3bb7799a749aa0685783854d"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/21/fc/d36a584ae61fe3fb26cb0ce751ff852f2960bd7eeef8165c7990a1cd873d/wrapt-2.2.0rc10-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "e0cf656100eab1193c99aa72fd5cd1906806396cb8f2ad47fb321128f2792fb2"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/6f/87/0748c676183e9043a35d85a665550909538b802b8057b97e56d2a11ecebd/wrapt-2.2.0rc10-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "452e3d297020447c7fae98bccbd7c4143b8d2c30e3a017698d85ba4130196d20"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/fa/29/c33ca4d544c7a730a8da0b1bf29fd142a5aea4c6d684c743c8686926b10a/wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e52c7612512a1b85a297e6faa0d37d0671ec578267d9ba5f3838f64c033017a9"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/5a/af/ffed7aa7d6fd82bf5d4d1a76f28ee731a190c59b2a8e1ccd48bba9168f16/wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_riscv64.whl",hashes = {sha256 = "4febff8cf99312b1dc8ae92c5bada78a6c4116d72600960b9e4f85d7df4c5d6e"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/cb/ca/59aa3a8c43927648ca87800ead94077959bd743f749fc357d416d619cdf7/wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "cc8b26679584ca894a8868dc12929a2ef5ec8ee3b0e8024a590d795388622bdb"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/8e/09/e7dfd67f78c461b77c086405f634159a3afacc332cfb76f137161f347b79/wrapt-2.2.0rc10-cp313-cp313-win32.whl",hashes = {sha256 = "8af9d7975322391bc02d38d1a3da8938dd6156136342305871a393ab0285e295"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/2b/07/0f54ad28efde3904c2a591ee930ef4152ae6f845223374e2934b67aa6eab/wrapt-2.2.0rc10-cp313-cp313-win_amd64.whl",hashes = {sha256 = "17dc46e6d4694d5d730beffded21bf2bcebe37524a70a830848e2a8f47b59ddf"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f0/64/1c40767fb1927407c4d83d0369cf33402ecea1b22319172d4f31e29f0e0d/wrapt-2.2.0rc10-cp313-cp313-win_arm64.whl",hashes = {sha256 = "fc66085eb491edda8212d4a0ab099bc63d3749ded586bb7cc8b69d85920a0b6d"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/67/26/7ec58ba818330401d201f73da511be833378513882aa8540b5763b3e6042/wrapt-2.2.0rc10-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "29757c68b28beeb067069ee8ee01035d5d954d093ad25aaa44d4079370886882"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d2/18/d960682d6cf45b2c29bcad2044c91460b5b6f3394e573db48188a0f18c3c/wrapt-2.2.0rc10-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "1bdba361bfaf684d075a216dc6fc0c1adf275c53553df963c0a83f4495f3e243"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/0a/6d/04cf4993a3ace28ae04d017b8ad04fdd5b3df94f20517f48fa02c98e5463/wrapt-2.2.0rc10-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "e2e64bb4a3949cb0ec2f1f11f7c8ec97dba6c70876e2d3351603a07cf0efa372"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/6b/83/f2fc1c2f29e95b2a5dc407119223f6d20e150a25b4ebaa79f16b58b870cc/wrapt-2.2.0rc10-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "f9abc7df75292ab960a751e40efce1c962b617c647058b727b97ab70036c56ac"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/a6/ac/91ab7fa8745960a5fe0a5777ac5c0e76ff8c82ce1a9455c22cc9f9d882c3/wrapt-2.2.0rc10-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "e7ea341d4a88193ba9b5a72cbb8c5959ca151b4b71c9dea999c49cf1d9735fbe"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/21/c3/516b870a4e2f23246dc933683d127c5096ad198492b2ae5734aba187fd40/wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "97f7e7e247f5004f318635ac37e6d365262f62f592b7f3fefd34f169000d41b5"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/0a/a7/faec7698cbdd88a4c1f7acdf74fc7c66af7f8d18e9142921a3fcffd60345/wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "084384abb5e3e87f2a9f86ed5b6dedab62c9a9ee5104dc6e49ae42e22e68d108"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/2e/e6/7ad025be96772d87ac9227a35d129410cdd1b2d3ee993c45dfeacd0e5855/wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "58d0a125067953e4a5486e3c41df551272aac8e98b919c6ad53972703be09675"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/d9/9f/c77fae78d2b5f8b441e4cb04d6377541bf268448cbf89d896dbad3134c86/wrapt-2.2.0rc10-cp313-cp313t-win32.whl",hashes = {sha256 = "ca33bb46a378620b4516dfd633aca279d1241afd542ddfda88ad42991a3bad5c"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d6/94/be15062160ae0783f1aa557d1c0aa823670ea9ec5899d8a575c891dea8bb/wrapt-2.2.0rc10-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "d7447f944dd86f4da04ac2df5e82c693c9af5ffdfc1894346cf806453b02ed2f"}}, + {name = "wrapt-2.2.0rc10-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ac/27/ddbbf81fe4915ebf8636938658b900102dad46d2eaf7041bf8a47c7ada63/wrapt-2.2.0rc10-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "f92832640a60e6c29445a65c2b82f672c458fada5de6f194e9f10d107efb8f94"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/1a/22/d6fbc4a54a46dabcea3c942fef82a6d4ecd68aca4e1f69a00e974157bcf0/wrapt-2.2.0rc10-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "c3b518b98cc711ef9b7d05fe44649b7da9c0cd3c9e60a826abd909c64a772668"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/62/fe/682c9351265288071332b65097c0c024897cc6eff183810c3fd76d7502c5/wrapt-2.2.0rc10-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "6d7c25fd90a0086e608a471a4c9e66855ebc3d143dfe31bad15ddf14338e30d3"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/ef/63/2df839d761645835263defa924a548675bacec5521b39498ed5df0901cb3/wrapt-2.2.0rc10-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "21a489d77869b7d030172f511142e140f4dfd4836a2426d0e26d2c913722fddd"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/c7/e3/aef5a0d55e779a30d07fc9af50bb3b504812aa8fa211461d2650f6c7d524/wrapt-2.2.0rc10-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "1664ec6d2f097548e45671c2171e485ddada066f89e1e1c599b208cf8693600f"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/dd/09/672121e17cea4c1c40f4ffa4f4aa3a19f5d50cff10a758602315b0029cb9/wrapt-2.2.0rc10-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "01913da074818dbc42e70155f05609f89d7745679a1938b1bef004b506defefa"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ba/df/00067f0faa27101bd04925e5e9db3172c43acf51e0d784b1c28d8ee0faf4/wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "26f50984cd44de71500c101a20fa9112c2577dd0b90446d3b1c24c64ab50b600"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/a1/f4/d006c6cfc3b17bb30ab0178c3b8905b029c1ca8d0142e548658f896507b6/wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_riscv64.whl",hashes = {sha256 = "5f0a7a2362e41d57cb99fc5fda425a7652d82bd0f4099ed0f4d224867d1f651c"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/8a/98/8831c1687a89f7e13b554e30d3e679c6d17a91d38d66907764037a5e0d87/wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "4410420729a63609c024d46368f03cff89b7d041dac8f6e45366ebd8b9d105aa"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/80/4e/5a58deecf5dc280f05ae77e088e728119c6b0d6e1b18a13b64ff9b794364/wrapt-2.2.0rc10-cp312-cp312-win32.whl",hashes = {sha256 = "6d5831bb3a05f7762fb51b519a329b17fd017ad7912b55727595d23a6b324a31"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/19/2a/ca0d3bab3a000b4351cce3ff5fa5343e653d8ebddea9cd41d4582be5d658/wrapt-2.2.0rc10-cp312-cp312-win_amd64.whl",hashes = {sha256 = "99d6725ec57c96e0de76f4b4005a89e3af166dafd1f0b40d2918a7cab1438811"}}, + {name = "wrapt-2.2.0rc10-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/9f/d0/13240f73f3515823a7581ad4ca0473d66ac9fe5bc5f66686c1ec40c4e8d6/wrapt-2.2.0rc10-cp312-cp312-win_arm64.whl",hashes = {sha256 = "dc3822c3cf5d11566fbfee24f0ed6e5d9a95a9f2667484b4239f6e5472078c09"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/32/5b/6e04a6fd699e6dc6c8e56725dfe4bb286a610d3b35aed6990a023bb89baf/wrapt-2.2.0rc10-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "3d61bb93dff6a605bc9f74a9c80e1c43449b939226c568403145ec2422996e4c"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/41/bf/060f27d7f35e9cae386c2d09d9e71731c9ce0afdcee7e48a8dc00f5d0623/wrapt-2.2.0rc10-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "fdce1de40216df2505d35fffc47ca52abae3fc94dd452478afa28258c1b1a6f5"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/b7/8d/3112c8f96eeb30283d3671c665823a5889b64bffae24d81febefb933fa94/wrapt-2.2.0rc10-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "c82c40e86a92e20576a6263799f3adf81e08f9162d8119ddc25e6d413482afa1"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/9f/8f/6c07a1a97723b055c1fc108d0a4ce4779986ec3939c953b6a18a1ffb4c00/wrapt-2.2.0rc10-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "582c49501f6feaa063a520edde2b94a7dfde231eab981cf3ca1b689b16d629d1"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/0e/43/263756369c58bfc8f2c58e27fdc21ec11e81780cd041b92d6384b3dd7373/wrapt-2.2.0rc10-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "5ae98df99924c5f9f6f9bdf0feab765d2ca848041d39b9f758eea4cd7c901535"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/a6/7b/bd0144efc848c5d600832fe68be8ecdda1151a1b580a295da5d6d86cc6a3/wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c10ef47939db9f7ba35aa371dd194dba468d0ec56273108a7e3cf2df1ccd336a"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/4e/a5/4265726936316449ba965adb9c3676c01322d43d6c5f9d261eba6d248657/wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_riscv64.whl",hashes = {sha256 = "c1bfac44eec4adb429f90a80a1911e9efe3a6b1159df92d410ca5ff06bb85d7e"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/1b/3f/b77d21e2bf08daeb591861fa9bf13b844144c171cd2a1ef7830225b9b002/wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ca7dc63028a782803b82a98b918f055f9210ae20691ca233378635fa3371ff4c"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/15/93/c149a4c7ef6e644a54c618623563db5b22021314ed134f52c615fbb58a5d/wrapt-2.2.0rc10-cp311-cp311-win32.whl",hashes = {sha256 = "e56c1307b8a53e5eb10a66f1a911de4d50dece6aabf8634d2a3dd0a081872948"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/88/d6/7445898124a66bcf19593a47ca6020e4a75bd29a293920525bb8380a9eca/wrapt-2.2.0rc10-cp311-cp311-win_amd64.whl",hashes = {sha256 = "6b47ccb8f33515af16a0cbdfddfa9c36a706de12956c638f24143ec08f813304"}}, + {name = "wrapt-2.2.0rc10-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f8/06/dd8768b0ff6fa2fd330c7709584ee6c9ca70ebc67fc4dd1244aa99569c11/wrapt-2.2.0rc10-cp311-cp311-win_arm64.whl",hashes = {sha256 = "3f093505afaccd298ed4c8408d76b8ec99ac064f505b15b9dc761635ba9af71a"}}, + {name = "wrapt-2.2.0rc10-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/0e/05/a900f438141dd89f13cc9e996a8c75498d3ade06c3116bc935cc4db7aac6/wrapt-2.2.0rc10-py3-none-any.whl",hashes = {sha256 = "da196d360b9e8a1fd8af6a484e581c4e6c20d5c496c4001983156392af28c470"}}, ] marker = "\"default\" in dependency_groups" @@ -3143,7 +3263,7 @@ marker = "\"default\" in dependency_groups" dependencies = [] [tool.pdm] -hashes = {sha256 = "3c7d5baee0bc97d17be158f336000b85517a6a15d5b6df73eb88e8617745d48d"} +hashes = {sha256 = "86eb729d27e9b8244f414b9667b932d8d485f9297e4ebe5d614b2a74fbf5dce2"} [[tool.pdm.targets]] requires_python = ">=3.11" From b72a78839595295a8aae9126e98ba19d997fd5b5 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 11:24:55 +0100 Subject: [PATCH 06/34] ci: set minimal runner timeouts on all jobs + remove exact version pinning for Scipy and statsmodels --- .github/workflows/build.yml | 14 +++++++++++--- .github/workflows/pre-commit.yml | 3 ++- .github/workflows/test.yml | 7 ++++++- pyproject.toml | 4 ++-- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2dcdf51..0b7e130 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,13 +1,18 @@ name: build on: + workflow_run: + workflows: Tests and Coverage + types: + - completed push: - branches: [main] + branches: main pull_request: jobs: - pre-commit: + build: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Checkout repository @@ -16,8 +21,11 @@ jobs: - name: Setup PDM uses: pdm-project/setup-pdm@94a823180e06fcde4ad29308721954a521c96ed0 - - name: Build artifacts + - name: Build package artifacts and install wheel run: | pdm build -v pdm add ./dist/isaricanalytics*.whl + + - name: Test wheel import + run: | python -c "import isaricanalytics; print(isaricanalytics.__version__)" diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index f9c0b50..0b69ee7 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -2,12 +2,13 @@ name: pre-commit on: push: - branches: [main] + branches: main pull_request: jobs: pre-commit: runs-on: ubuntu-latest + timeout-minutes: 2 steps: - name: Checkout repository diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 26cf6e1..3f2fafb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,10 @@ name: Tests and Coverage -"on": +on: + workflow_run: + workflows: pre-commit + types: + - completed push: branches: - main @@ -9,6 +13,7 @@ name: Tests and Coverage jobs: unit-test: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Checkout repository diff --git a/pyproject.toml b/pyproject.toml index ee82007..ab495cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,8 +41,8 @@ dependencies = [ "plotly==6.1.1", "requests>=2.32.4", "scikit-learn==1.5.2", - "scipy==1.12.0", - "statsmodels==0.14.1", + "scipy>=1.12.0", + "statsmodels>=0.14.1", ] [project.optional-dependencies] From 33ca87d7453c9d26a37cff3999a52a6d0bba250a Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 11:39:13 +0100 Subject: [PATCH 07/34] ci: simplify build workflow - use PyPA `build` instead of PDM --- .github/workflows/build.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b7e130..330f82e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,13 +18,14 @@ jobs: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - - name: Setup PDM - uses: pdm-project/setup-pdm@94a823180e06fcde4ad29308721954a521c96ed0 + - name: Install build dependencies + run: | + pip install -U pip build - name: Build package artifacts and install wheel run: | - pdm build -v - pdm add ./dist/isaricanalytics*.whl + python -m build + pip install dist/isaricanalytics*.whl - name: Test wheel import run: | From 5792950ff578d267a0facd1a888599f293d09877 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 13:14:24 +0100 Subject: [PATCH 08/34] ci: increase job timeouts --- .github/workflows/build.yml | 2 +- .github/workflows/pre-commit.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 330f82e..b422605 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ on: jobs: build: runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 30 steps: - name: Checkout repository diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 0b69ee7..6de71ec 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -8,7 +8,7 @@ on: jobs: pre-commit: runs-on: ubuntu-latest - timeout-minutes: 2 + timeout-minutes: 10 steps: - name: Checkout repository diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f2fafb..1f9ac25 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ on: jobs: unit-test: runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 30 steps: - name: Checkout repository From d83bff1831544b7739c4b664b742655a7cf45903 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 17 Apr 2026 13:26:19 +0100 Subject: [PATCH 09/34] chore: rename the core libs + update refs in tests --- isaricanalytics/{IsaricAnalytics.py => analytics.py} | 0 isaricanalytics/{getREDCapData.py => redcap_data.py} | 0 isaricanalytics/{IsaricDraw.py => visualisation.py} | 0 tests/unit/test_analytics.py | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename isaricanalytics/{IsaricAnalytics.py => analytics.py} (100%) rename isaricanalytics/{getREDCapData.py => redcap_data.py} (100%) rename isaricanalytics/{IsaricDraw.py => visualisation.py} (100%) diff --git a/isaricanalytics/IsaricAnalytics.py b/isaricanalytics/analytics.py similarity index 100% rename from isaricanalytics/IsaricAnalytics.py rename to isaricanalytics/analytics.py diff --git a/isaricanalytics/getREDCapData.py b/isaricanalytics/redcap_data.py similarity index 100% rename from isaricanalytics/getREDCapData.py rename to isaricanalytics/redcap_data.py diff --git a/isaricanalytics/IsaricDraw.py b/isaricanalytics/visualisation.py similarity index 100% rename from isaricanalytics/IsaricDraw.py rename to isaricanalytics/visualisation.py diff --git a/tests/unit/test_analytics.py b/tests/unit/test_analytics.py index f8a987c..4226f85 100644 --- a/tests/unit/test_analytics.py +++ b/tests/unit/test_analytics.py @@ -1,6 +1,6 @@ import pandas as pd -from isaricanalytics.IsaricAnalytics import ( +from isaricanalytics.analytics import ( convert_categorical_to_onehot, convert_onehot_to_categorical, from_timeA_to_timeB, From 3a5b1cb4fabb60df30357c46cbe0025fb2ef7ded Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Mon, 20 Apr 2026 10:37:14 +0100 Subject: [PATCH 10/34] chore: bump version to `0.2.0` --- isaricanalytics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/isaricanalytics/__init__.py b/isaricanalytics/__init__.py index 3dc1f76..d3ec452 100644 --- a/isaricanalytics/__init__.py +++ b/isaricanalytics/__init__.py @@ -1 +1 @@ -__version__ = "0.1.0" +__version__ = "0.2.0" From 71d371927c1e47775215cddf26ca63d59e93326c Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Tue, 21 Apr 2026 11:39:28 +0100 Subject: [PATCH 11/34] chore: type hinting, docstrings, and tidying up in `visualisation` --- isaricanalytics/visualisation.py | 1317 +++++++++++++++++------------- 1 file changed, 762 insertions(+), 555 deletions(-) diff --git a/isaricanalytics/visualisation.py b/isaricanalytics/visualisation.py index 5560eaa..4f12900 100644 --- a/isaricanalytics/visualisation.py +++ b/isaricanalytics/visualisation.py @@ -1,56 +1,40 @@ -import json -import os -import sys - +__all__ = [ + "fig_bar_chart", + "fig_bar_line_chart", + "fig_count_chart", + "fig_dual_stack_pyramid", + "fig_flowchart", + "fig_forest_plot", + "fig_frequency_chart", + "fig_heatmaps", + "fig_kaplan_meier", + "fig_line_chart", + "fig_pie", + "fig_placeholder", + "fig_sankey", + "fig_sunburst", + "fig_table", + "fig_text", + "fig_timelines", + "fig_upset", + "hex_to_rgb", + "hex_to_rgba", + "rgb_to_rgba", +] + +# -- IMPORTS -- + +# -- Standard libraries -- +import typing + +# -- 3rd party libraries -- import numpy as np import pandas as pd import plotly.express as px import plotly.graph_objs as go from plotly.subplots import make_subplots - -def get_graph_id(suffix, frame=1): - fig_name = sys._getframe(frame).f_code.co_name - graph_id = suffix + "/" + fig_name - return graph_id - - -def save_inputs_to_file(local_args): - fig_name = sys._getframe(1).f_code.co_name - # Create and use a copy - _local_args = dict(local_args) - data = _local_args.pop("data") - # Convert to list (if not already) - data = data if isinstance(data, tuple) else (data,) - path = _local_args["filepath"] - suffix = _local_args["suffix"] - - if _local_args["graph_id"] is None: - graph_id = get_graph_id(_local_args["suffix"], frame=2) - else: - graph_id = suffix + "/" + _local_args["graph_id"] - - fig_data = [graph_id + "_data___" + str(ii) + ".csv" for ii in range(len(data))] - _local_args["graph_id"] = None - _local_args["filepath"] = "" - _local_args["save_inputs"] = False - metadata = { - "fig_id": graph_id, - "fig_name": fig_name, - "fig_arguments": _local_args, - "fig_data": fig_data, - } - os.makedirs(os.path.dirname(path), exist_ok=True) - metadata_json_file = os.path.join(path, graph_id + "_metadata.json") - with open(metadata_json_file, "w") as file: - json.dump(metadata, file, indent=4) - file.write("\n") - for ii in range(len(data)): - data[ii].to_csv( - os.path.join(path, graph_id + "_data___" + str(ii) + ".csv"), index=False - ) - return data, metadata - +# -- Internal libraries -- ############################################ ############################################ @@ -60,29 +44,36 @@ def save_inputs_to_file(local_args): def fig_placeholder( - data, - title="Placeholder scatter plot", - xlabel="", - ylabel="", - height=450, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Placeholder scatter plot", + xlabel: str = "", + ylabel: str = "", + height: int = 450, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a placeholder scatter plot. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Placeholder scatter plot" + Figure title. + + xlabel : str, default="" + Figure x-axis label. + + ylabel : str, default="" + Figure y-axis label. + + height : int, default=450 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ if data is None: x = [1, 2, 3, 4, 5] y = np.random.uniform(low=10, high=15, size=5) @@ -105,38 +96,51 @@ def fig_placeholder( minreducedwidth=500, ) - # ---- - # Every figure return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_pie( - data, - title="Pie chart", - xlabel="", - ylabel="", - base_color_map=None, - names="", - values="", - height=450, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", + data: pd.DataFrame, + title: str = "Pie chart", + xlabel: str = "", + ylabel: str = "", + base_color_map: dict[str, str] | None = None, + names: str | int | pd.Series | typing.Iterable = "", + values: str | int | pd.Series | typing.Iterable = "", + height: int = 450, ): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) + """:py:class:`go.Figure` : Returns a pie chart figure. - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Placeholder scatter plot" + Figure title. + + xlabel : str, default="" + Figure x-axis label. + + ylabel : str, default="" + Figure y-axis label. + + base_color_map : dict + Map of sector values/marks and colours. + + names : str, int, pd.Series, typing.Iterable, default="" + Sector label(s). + + values : str, int, pd.Series, typing.Iterable, default="" + height : int, default=450 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() fig = px.pie( @@ -156,40 +160,60 @@ def fig_pie( minreducedwidth=500, ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_timelines( - data, - title="Timeline", - label_col="", - group_col="", - start_date="start_date", - end_date="end_date", - size_col=None, - min_width=2, - max_width=10, - height=500, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Timeline", + label_col: str = "", + group_col: str = "", + start_date: str = "start_date", + end_date: str = "end_date", + size_col: str | None = None, + min_width: int = 2, + max_width: int = 10, + height: int = 500, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a timeline figure. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Timeline" + Figure title. + + label_col : str, default="" + Label column. + + group_col : str, default="" + Group column. + + start_date : str, default="start_date" + Start date column. + + end_date : str, default="end_date" + End date column. + + size_col : str, None, default=None + Size column. + + min_width : int, default=2 + Figure minimum width. + + max_width : int, default=10 + Figure maximum width. + + height : int, default=500 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() df[start_date] = pd.to_datetime(df[start_date]) df[end_date] = pd.to_datetime(df[end_date]) @@ -260,36 +284,45 @@ def fig_timelines( minreducedwidth=500, ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_sunburst( - data, - title="Sunburst Chart", - path=["level0", "level1"], - values="values", - base_color_map=None, - height=430, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Sunburst Chart", + path: list[str | int] | pd.Series | typing.Iterable | None = ["level0", "level1"], + values: str | int | pd.Series | typing.Iterable = "values", + base_color_map: dict[str, str] | None = None, + height: int = 430, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a sunburst plot. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Sunburst Chart" + Figure title. + + path : str, int, pd.Series, typing.Iterable, None, default=["level0", "level1"] + Column names defining a hierarhy of sectors, from root to leaves. + + values : str, int, pd.Series, typing.Iterable, default="values" + A column name in the data defining sector values, or a Pandas Series + or an iterable containing sector values. + + base_color_map : dict, default=None + Map of sector values/marks and colours. + + height : int, default=430 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() fig = px.sunburst( @@ -312,39 +345,58 @@ def fig_sunburst( minreducedwidth=500, ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_bar_chart( - data, - title="Bar Chart", - xlabel="", - ylabel="", - index_column="index", - barmode="stack", - xaxis_tickformat="%m-%Y", - base_color_map=None, - height=340, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Bar Chart", + xlabel: str = "", + ylabel: str = "", + index_column: str = "index", + barmode: str = "stack", + xaxis_tickformat: str = "%m-%Y", + base_color_map: dict[str, str] | None = None, + height: int = 340, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a bar chart + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Bar Chart" + Figure title. + + xlabel : str, default="" + Figure x-axis label. + + ylabel : str, default="" + Figure y-axis label. + + index_column : str, default="index" + Index column. + + barmode : str, default="stack" + How bars with the same location coordinate are displayed: possible + values are `"stack"`, `"relative"`, `"group"`, `"overlay"``. For + reference see the `Plotly documentation `_. + + xaxis_tickformat : str, default="%m-%Y" + x-axis tick format. + + base_color_map : dict, default=None + Map of bar values and colours. + + height : int, default=340 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() df = df.set_index(index_column) @@ -397,33 +449,32 @@ def fig_bar_chart( ) fig = go.Figure(data=traces, layout=layout) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_upset( - data, - title="Upset Plot", - height=480, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Upset Plot", + height: int = 480, +) -> go.Figure: + """:py:class:`go.Figure` : Returns an upset plot. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Upset Plot" + Figure title. + + height : int, default=480 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ counts = data[0].copy() intersections = data[1].copy() @@ -582,36 +633,44 @@ def fig_upset( minreducedwidth=500, ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_count_chart( - data, - title="Count Chart", - xlabel="Count", - ylabel="Variable", - base_color_map=None, - height=350, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Count Chart", + xlabel: str = "Count", + ylabel: str = "Variable", + base_color_map: dict[str, str] | None = None, + height: int = 350, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a count chart. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Count Chart" + Figure title. + + xlabel : str, default="Count" + Figure x-axis label. + + ylabel : str, default="Variable" + Figure y-axis label. + + base_color_map : dict, default=None + Map of bar values and colours. + + height : int, default=350 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() column_names = ["label", "count", "short_label"] @@ -676,36 +735,44 @@ def fig_count_chart( fig = go.Figure(data=traces, layout=layout) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_frequency_chart( - data, - title="Frequency Chart", - xlabel="Proportion", - ylabel="Variable", - base_color_map=None, - height=350, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Frequency Chart", + xlabel: str = "Proportion", + ylabel: str = "Variable", + base_color_map: dict[str, str] | None = None, + height: int = 350, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a frequency chart. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Frequency Chart" + Figure title. + + xlabel : str, default="Proportion" + Figure x-axis label. + + ylabel : str, default="Variable" + Figure y-axis label. + + base_color_map : dict + Map of bar values and colours. + + height : int, default=350 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() column_names = ["label", "proportion", "short_label"] @@ -794,34 +861,33 @@ def fig_frequency_chart( fig = go.Figure(data=traces, layout=layout) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_table( - data, - table_key="", - columnwidth=None, - height=500, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + table_key: str = "", + columnwidth: int | None = None, + height: int = 500, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a table figure. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + table_key : str, default="" + Table key. + + height : int, default=500 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() bf_columns = ["" + x + "" for x in df.columns] @@ -863,36 +929,44 @@ def fig_table( minreducedwidth=500, ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_dual_stack_pyramid( - data, - title="Dual-Sided Stacked Pyramid Chart", - xlabel="Count", - ylabel="Category", - base_color_map=None, - height=430, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: go.Figure, + title: str = "Dual-Sided Stacked Pyramid Chart", + xlabel: str = "Count", + ylabel: str = "Category", + base_color_map: dict[str, str] | None = None, + height: int = 430, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a dual-sided stacked pyramid chart. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Dual-Sided Stacked Pyramid Chart" + Figure title. + + xlabel : str, default="Count" + Figure x-axis label. + + ylabel : str, default="Category" + Figure y-axis label. + + base_color_map : dict, default=None + Map of bar values and colours. + + height : int, default=430 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() # Error Handling @@ -1029,32 +1103,28 @@ def fig_dual_stack_pyramid( ) fig = go.Figure(data=traces, layout=layout) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_flowchart( - data, - height=430, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + height: int = 430, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a flowchart. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + height : int, default=430 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() arrows = [] @@ -1115,39 +1185,56 @@ def fig_flowchart( fig = go.Figure(layout=layout) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_forest_plot( - data, - title="Forest Plot", - xlabel="Odds Ratio (95% CI)", - ylabel="", - reorder=True, - labels=["Variable", "OddsRatio", "LowerCI", "UpperCI"], - marker=None, - noeffect_line=True, - height=600, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Forest Plot", + xlabel: str = "Odds Ratio (95% CI)", + ylabel: str = "", + reorder: bool = True, + labels: typing.Iterable[str] = ["Variable", "OddsRatio", "LowerCI", "UpperCI"], + marker: dict[str, typing.Any] | None = None, + noeffect_line: bool = True, + height: int = 600, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a forest plot. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Forest Plot" + Figure title. + + xlabel : str, default="Odds Ratio (95% CI)" + Figure x-axis label. + + ylabel : str, default="" + Figure y-axis label. + + reorder : bool, default=True + Sort values. + + labels : typing.Iterable, default=["Variable", "OddsRatio", "LowerCI", "UpperCI"] + Column of labels. + + marker : dict, default=None + Marker properties dict. + + no_effect_line : bool, default=True + Add no effect line. + + height : int, default=600 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() # Ordering Values -> Descending Order @@ -1228,32 +1315,28 @@ def fig_forest_plot( ) fig = go.Figure(data=traces, layout=layout) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_text( - data, - height=430, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + height: int = 430, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a figure with an annotation. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + height : int, default=430 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ fig = go.Figure() text = "
".join(data["paragraphs"].values) @@ -1269,40 +1352,60 @@ def fig_text( minreducedwidth=500, ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_kaplan_meier( - data, - title="Kaplan-Meier Plot", - xlabel="Time (days)", - ylabel="Survival Probability", - groups=None, - index_column="index", - base_color_map=None, - xlim=None, - p_value=None, - height=800, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Kaplan-Meier Plot", + xlabel: str = "Time (days)", + ylabel: str = "Survival Probability", + height: int = 480, + groups: typing.Iterable[str] | None = None, + index_column: str = "index", + base_color_map: dict[str, str] | None = None, + xlim: typing.Iterable[float | int] | None = None, + p_value: float | None = None, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a Kaplan-Meier plot. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Kaplan-Meier Plot" + Figure title. + + xlabel : str, default="Time (days)" + Figure x-axis label. + + ylabel : str, default="Survival Probability" + Figure y-axis label. + + height : int, default=480 + Figure height. + + groups : typing.Iterable, default=None + Groups. + + index_column : str, default="index" + Index column. + + base_color_map : dict, default=None + Colour map. + + xlim : typing.Iterable, default=None + xlim. + + p_value : float, default=None + p-value. + + Returns + ------- + go.Figure + The figure. + """ df_km = data[0].copy() risk_table = data[1].copy() @@ -1504,40 +1607,60 @@ def fig_kaplan_meier( minreducedwidth=500, ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_line_chart( - data, - title="Line chart", - xlabel="", - ylabel="", - line_column="", - index_column="index", - lower_column=None, - upper_column=None, - line_color=None, - height=340, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Line chart", + xlabel: str = "", + ylabel: str = "", + height: int = 480, + line_column: str = "", + index_column: str = "index", + lower_column: str | None = None, + upper_column: str | None = None, + line_color: str | None = None, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a line chart. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Line chart" + Figure title. + + xlabel : str, default="" + Figure x-axis label. + + ylabel : str, default="" + Figure y-axis label. + + height : int, default=480 + Figure height. + + line_column : str, default="" + Line column. + + index_column : str, default="index" + Index column. + + lower_column : str, default=None + Lower column. + + upper_column : str, default=None + Upper column. + + line_color : str, default=None + Line colour. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() # Ensure correct index @@ -1592,43 +1715,69 @@ def fig_line_chart( fig = go.Figure(data=data, layout=layout) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_bar_line_chart( - data, - title="Combined bar line chart", - xlabel="", - ylabel_left="", - ylabel_right="", - bar_column="", - line_column="", - index_column="index", - lower_column=None, - upper_column=None, - bar_color=None, - line_color=None, - height=500, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "Combined bar line chart", + xlabel: str = "", + ylabel_left: str = "", + ylabel_right: str = "", + bar_column: str = "", + line_column: str = "", + index_column: str = "index", + lower_column: str | None = None, + upper_column: str | None = None, + bar_color: str | None = None, + line_color: str | None = None, + height: int = 500, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a bar-line chart. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="Combined bar line chart" + Figure title. + + xlabel : str, default="" + Figure x-axis label. + + ylabel : str, default="" + Figure y-axis label. + + bar_column : str, default="" + Bar column. + + line_column : str, default="" + Line column. + + index_column : str, default="index" + Index column. + + lower_column : str, default=None + Lower column. + + upper_column : str, default=None + Upper column. + + bar_color : str, default=None + Bar colour. + + line_color : str, default=None + Line colour. + + height : int, default=500 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ df = data.copy() # Ensure correct index @@ -1705,42 +1854,68 @@ def fig_bar_line_chart( ) fig = go.Figure(data=data, layout=layout) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_heatmaps( - data, - title="", - subplot_titles=None, - ylabel="", - xlabel="", - colorbar_label="", - index_column="index", - zmin=None, - zmax=None, - include_annotations=False, - base_color_map=None, - height=750, - suffix="", - filepath="", - save_inputs=False, - graph_id=None, - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + title: str = "", + subplot_titles: list[str] | None = None, + ylabel: str = "", + xlabel: str = "", + colorbar_label: str = "", + index_column: str = "index", + zmin: float | None = None, + zmax: float | None = None, + include_annotations: bool = False, + base_color_map: dict[str, str] | None = None, + height: int = 750, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a heatmaps chart. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + title : str, default="" + Figure title. + + subplot_titles : list, default=None + Subplot titles. + + xlabel : str, default="" + Figure x-axis label. + + ylabel : str, default="" + Figure y-axis label. + + colorbar_label : str, default="" + Colour bar label. + + index_column : str, default="index" + Index column. + + zmin : float, default=None + zmin. + + zmax : float, default=None + zmax. + + include_annotations : bool, default=False + Include annotations. + + base_color_map : dict, default=None + Colour map. + + height : int, default=750 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ if isinstance(data, tuple) is False: data = (data,) @@ -1809,32 +1984,28 @@ def fig_heatmaps( col=1, ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig def fig_sankey( - data, - height=500, - suffix="", - filepath="", - save_inputs=False, - graph_id="sankey", - graph_label="", - graph_about="", -): - # ---- - # Every figure must start with this - if save_inputs: - inputs = save_inputs_to_file(locals()) - - if graph_id is None: - graph_id = get_graph_id(suffix) - else: - graph_id = suffix + "/" + graph_id - # ---- - + data: pd.DataFrame, + height: int = 500, +) -> go.Figure: + """:py:class:`go.Figure` : Returns a Sankey plot. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + height : int, default=500 + Figure height. + + Returns + ------- + go.Figure + The figure. + """ node = data[0].copy() link = data[1].copy() annotations = data[2].copy() @@ -1866,9 +2037,7 @@ def fig_sankey( ), ) - # ---- - # Every figure must return the same outputs - return fig, graph_id, graph_label, graph_about + return fig ############################################ @@ -1878,14 +2047,42 @@ def fig_sankey( ############################################ -def hex_to_rgb(hex_color): - """Convert a hex color to an RGB tuple.""" +def hex_to_rgb(hex_color: str) -> tuple[int]: + """:py:class:`tuple` : Converts a hex colour to an RGB colour tuple. + + Parameters + ---------- + hex_color : str + Hex colour string. + + Returns + ------- + tuple + RGB int tuple. + """ hex_color = hex_color.lstrip("#") rgb_color = tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) return rgb_color -def hex_to_rgba(hex_color, opacity): +def hex_to_rgba(hex_color: str, opacity: float) -> str: + """:py:class:`str` : Converts a hex colour to an RGBA (red-green-blue-alpha) + colour string. + + Parameters + ---------- + hex_color : str + Hex colour string. + + opacity : float + Opacity/transparency, a value between 0.0 (fully transparent) and + 1.0 (fully opaque). + + Returns + ------- + str + An RGBA colour string (RGB + opacity/transparency). + """ hex_color = hex_color.lstrip("#") hlen = len(hex_color) rgba_color = "rgba(" + ", ".join( @@ -1895,12 +2092,22 @@ def hex_to_rgba(hex_color, opacity): return rgba_color -def rgb_to_rgba(rgb_value, alpha): - """ - Adds the alpha channel to an RGB Value and returns it as an RGBA Value - :param rgb_value: Input RGB Value - :param alpha: Alpha Value to add in range [0,1] - :return: RGBA Value - """ +def rgb_to_rgba(rgb_value: tuple[int], alpha: float) -> str: + """:py:class:`str` : Converts an RGB colour tuple and alpha value to an RGBA colour string. + + Parameters + ---------- + rgb_value : tuple + RGB int tuple. + + alpha : float + Opacity/transparency value between 0.0 (fully transparent) and 1.0 + (fully opaque). + + Returns + ------- + str + RGBA colour string. + """ # noqa: E501 rgba_color = f"rgba{rgb_value[3:-1]}, {alpha})" return rgba_color From 0c361353780151f3c928329b762f601ea4a1fe7c Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 24 Apr 2026 12:14:48 +0100 Subject: [PATCH 12/34] test: unit tests for most `visualisation` functions, and a few functions elsewhere --- .github/workflows/test.yml | 3 +- isaricanalytics/redcap_data.py | 60 +- isaricanalytics/utils.py | 88 +++ isaricanalytics/visualisation.py | 46 +- tests/unit/assets/conversion_table.csv | 14 + tests/unit/assets/countries.csv | 219 +++++++ tests/unit/test_redcap_data.py | 90 +++ tests/unit/test_utils.py | 39 ++ tests/unit/test_visualisation.py | 833 +++++++++++++++++++++++++ 9 files changed, 1338 insertions(+), 54 deletions(-) create mode 100644 isaricanalytics/utils.py create mode 100644 tests/unit/assets/conversion_table.csv create mode 100644 tests/unit/assets/countries.csv create mode 100644 tests/unit/test_redcap_data.py create mode 100644 tests/unit/test_utils.py create mode 100644 tests/unit/test_visualisation.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1f9ac25..488077d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,8 @@ jobs: -p pytest_cov \ --cov=isaricanalytics \ --cov-report=term-missing \ - --cov-report=xml + --cov-report=xml \ + --cov-report=html - name: Upload coverage.xml artifact uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f diff --git a/isaricanalytics/redcap_data.py b/isaricanalytics/redcap_data.py index 459c292..36a4454 100644 --- a/isaricanalytics/redcap_data.py +++ b/isaricanalytics/redcap_data.py @@ -555,7 +555,7 @@ def map_variable(variable, mapping_dict, other_value_str="Other / Unknown"): return variable -def load_conversion_table() -> pd.DataFrame: +def load_units_conversion_table() -> pd.DataFrame: """:py:class:`pandas.DataFrame` : Loads the conversion table from a CSV. Returns @@ -564,51 +564,45 @@ def load_conversion_table() -> pd.DataFrame: The conversion table. """ try: - # Lookup table in an `assets` subfolder of the current folder + # Lookup table in an `assets` subfolder adjacent to the current folder return pd.read_csv( - Path(__file__).parent.joinpath("assets", "conversion_table.csv") + Path(__file__).parent.parent.joinpath("assets", "conversion_table.csv") ) except FileNotFoundError: - try: - # Lookup table in an `assets` subfolder of the parent folder - return pd.read_csv( - Path(__file__).parent.parent.joinpath("assets", "conversion_table.csv") - ) - except FileNotFoundError: - # Otherwise just get it from VERTEX assets on GitHub - return pd.read_csv( - "https://raw.githubusercontent.com/ISARICResearch/" - "VERTEX/refs/heads/main/assets/conversion_table.csv" - ) + # Otherwise just get it from VERTEX assets on GitHub + return pd.read_csv( + "https://raw.githubusercontent.com/ISARICResearch/" + "VERTEX/refs/heads/main/assets/conversion_table.csv" + ) -def load_countries(encoding="latin-1") -> pd.DataFrame: +def load_countries_table(encoding: str = "latin-1") -> pd.DataFrame: """:py:class:`pandas.DataFrame` : Loads countries from a CSV. + Parameters + ---------- + encoding : str, default="latin-1" + Optional file encoding. + Returns ------- pd.DataFrame - The conversion table. + The countries table. """ try: - # Lookup table in an `assets` subfolder of the current folder + # Lookup table in an `assets` subfolder adjacent to the current + # folder. return pd.read_csv( - Path(__file__).parent.joinpath("assets", "countries.csv"), encoding=encoding + Path(__file__).parent.parent.joinpath("assets", "countries.csv"), + encoding=encoding, ) except FileNotFoundError: - try: - # Lookup table in an `assets` subfolder of the parent folder - return pd.read_csv( - Path(__file__).parent.parent.joinpath("assets", "countries.csv"), - encoding=encoding, - ) - except FileNotFoundError: - # Otherwise just get it from VERTEX assets on GitHub - return pd.read_csv( - "https://raw.githubusercontent.com/ISARICResearch/" - "VERTEX/refs/heads/main/assets/countries.csv", - encoding=encoding, - ) + # Otherwise just get it from VERTEX assets on GitHub + return pd.read_csv( + "https://raw.githubusercontent.com/ISARICResearch/" + "VERTEX/refs/heads/main/assets/countries.csv", + encoding=encoding, + ) def homogenise_variables(df, dictionary): @@ -623,7 +617,7 @@ def homogenise_variables(df, dictionary): pd.DataFrame: DataFrame with all specified values converted to the desired units. """ - conversion_table = load_conversion_table() + conversion_table = load_units_conversion_table() for index, row in conversion_table.iterrows(): from_unit = row["from_unit"] to_unit = row["to_unit"] @@ -954,7 +948,7 @@ def get_redcap_data( ) if "demog_country" in dictionary["field_name"].values: - countries = load_countries(encoding="latin-1") + countries = load_countries_table(encoding="latin-1") df_map["country_iso"] = df_map["demog_country"].replace( dict(zip(countries["Country"], countries["Code"])) ) diff --git a/isaricanalytics/utils.py b/isaricanalytics/utils.py new file mode 100644 index 0000000..1e20a7e --- /dev/null +++ b/isaricanalytics/utils.py @@ -0,0 +1,88 @@ +__all__ = [ + "clean_figure_table", + "strip_html", + "strip_nonstandard_unicode_chars", +] + +# -- IMPORTS -- + +# -- Standard libraries -- +import re +import typing + +# -- 3rd party libraries -- +import pandas as pd + +# -- Internal libraries -- + + +def strip_html(value: typing.Any) -> str | typing.Any: + """:py:class:`typing.Any` : Strip HTML elements from a value. + + Parameters + ---------- + value : typing.Any + A value. + + Returns + ------- + str, typing.Any + Either a string stripped of all HTML elements, or the original non- + string value. + """ + if isinstance(value, str): + return re.sub(r"<.*?>", "", value) + + return value + + +def strip_nonstandard_unicode_chars(value: typing.Any) -> str | typing.Any: + """:py:class:`typing.Any` : Strip non-standard Unicode characters from a value. + + The non-standard Unicode characters of interest are defined within the + function itself, and are currently limited to the "↳" (U+21B3) character, + but may be extended to include other characters. + + Parameters + ---------- + value : typing.Any + A value. + + Returns + ------- + str, typing.Any + Either a string stripped of all non-standard Unicode characters, or the + original non- string value. + """ + nonstandard_unicode_chars = "↳" + + if isinstance(value, str): + return re.sub(rf"[{nonstandard_unicode_chars}]", "", value) + + return value + + +def clean_figure_table(figure_table: pd.DataFrame) -> pd.DataFrame: + """:py:class:pandas.DataFrame : A cleaned figure table dataframe. + + The cleaning steps are unique to the Plotly graph object table format from + which the table CSVs were originally, which contain HTML styling elements + and non-standard (non-alphabetic) Unicode characters. The cleaning is the + removal of such characters. + + Parameters + ---------- + figure_table : pandas.DataFrame + The original figure table as a Pandas dataframe. + + Returns + ------- + pandas.DataFrame + The cleaned figure table. + """ + # The use of `pandas.DataFrame.map` here is not absolutely optimal, as + # `map` applies changes across the dataframe element-wise, but is the + # safer choice given that the dataframe may contain a number of non-string + # columns which cannot be known in advance, while the cleaning steps + # currently only apply to string values. + return figure_table.map(strip_html).map(strip_nonstandard_unicode_chars) diff --git a/isaricanalytics/visualisation.py b/isaricanalytics/visualisation.py index 4f12900..3c45afa 100644 --- a/isaricanalytics/visualisation.py +++ b/isaricanalytics/visualisation.py @@ -126,12 +126,13 @@ def fig_pie( Figure y-axis label. base_color_map : dict - Map of sector values/marks and colours. + Map of sector values and colours. names : str, int, pd.Series, typing.Iterable, default="" - Sector label(s). + Sector name(s)/label(s). values : str, int, pd.Series, typing.Iterable, default="" + Sector values. height : int, default=450 Figure height. @@ -359,7 +360,7 @@ def fig_bar_chart( base_color_map: dict[str, str] | None = None, height: int = 340, ) -> go.Figure: - """:py:class:`go.Figure` : Returns a bar chart + """:py:class:`go.Figure` : Returns a bar chart. Parameters ---------- @@ -453,7 +454,7 @@ def fig_bar_chart( def fig_upset( - data: pd.DataFrame, + data: tuple[pd.DataFrame], title: str = "Upset Plot", height: int = 480, ) -> go.Figure: @@ -461,8 +462,9 @@ def fig_upset( Parameters ---------- - data : pd.DataFrame - Incoming data. + data : tuple + Incoming data as two Pandas dataframes, the first for counts, and the + second for intersections. title : str, default="Upset Plot" Figure title. @@ -867,7 +869,7 @@ def fig_frequency_chart( def fig_table( data: pd.DataFrame, table_key: str = "", - columnwidth: int | None = None, + columnwidth: typing.Iterable[int | float] | None = None, height: int = 500, ) -> go.Figure: """:py:class:`go.Figure` : Returns a table figure. @@ -880,6 +882,9 @@ def fig_table( table_key : str, default="" Table key. + columnwidth : typing.Iterable, default=None + An iterable of column widths. + height : int, default=500 Figure height. @@ -933,7 +938,7 @@ def fig_table( def fig_dual_stack_pyramid( - data: go.Figure, + data: pd.DataFrame, title: str = "Dual-Sided Stacked Pyramid Chart", xlabel: str = "Count", ylabel: str = "Category", @@ -1356,23 +1361,24 @@ def fig_text( def fig_kaplan_meier( - data: pd.DataFrame, + data: tuple[pd.DataFrame], title: str = "Kaplan-Meier Plot", xlabel: str = "Time (days)", ylabel: str = "Survival Probability", - height: int = 480, groups: typing.Iterable[str] | None = None, index_column: str = "index", base_color_map: dict[str, str] | None = None, xlim: typing.Iterable[float | int] | None = None, p_value: float | None = None, + height: int = 480, ) -> go.Figure: """:py:class:`go.Figure` : Returns a Kaplan-Meier plot. Parameters ---------- - data : pd.DataFrame - Incoming data. + data : tuple + Incoming data as two Pandas dataframes, the first for the plot, and the + second for the risk table. title : str, default="Kaplan-Meier Plot" Figure title. @@ -1383,9 +1389,6 @@ def fig_kaplan_meier( ylabel : str, default="Survival Probability" Figure y-axis label. - height : int, default=480 - Figure height. - groups : typing.Iterable, default=None Groups. @@ -1401,6 +1404,9 @@ def fig_kaplan_meier( p_value : float, default=None p-value. + height : int, default=480 + Figure height. + Returns ------- go.Figure @@ -2058,7 +2064,7 @@ def hex_to_rgb(hex_color: str) -> tuple[int]: Returns ------- tuple - RGB int tuple. + RGB colour tuple. """ hex_color = hex_color.lstrip("#") rgb_color = tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) @@ -2092,13 +2098,13 @@ def hex_to_rgba(hex_color: str, opacity: float) -> str: return rgba_color -def rgb_to_rgba(rgb_value: tuple[int], alpha: float) -> str: +def rgb_to_rgba(rgb_color: tuple[int], alpha: float) -> str: """:py:class:`str` : Converts an RGB colour tuple and alpha value to an RGBA colour string. Parameters ---------- - rgb_value : tuple - RGB int tuple. + rgb_color : tuple + RGB color tuple. alpha : float Opacity/transparency value between 0.0 (fully transparent) and 1.0 @@ -2109,5 +2115,5 @@ def rgb_to_rgba(rgb_value: tuple[int], alpha: float) -> str: str RGBA colour string. """ # noqa: E501 - rgba_color = f"rgba{rgb_value[3:-1]}, {alpha})" + rgba_color = f"rgba({rgb_color[0]}, {rgb_color[1]}, {rgb_color[2]}, {alpha})" return rgba_color diff --git a/tests/unit/assets/conversion_table.csv b/tests/unit/assets/conversion_table.csv new file mode 100644 index 0000000..71db60a --- /dev/null +++ b/tests/unit/assets/conversion_table.csv @@ -0,0 +1,14 @@ +from_unit,to_unit,variable,variable_unit,conversion_factor +umol/L,mg/dL,labs_creatinine,labs_creatinine_units,88.4 +mmol/L,mg/dL,labs_ureanitro,labs_ureanitro_units,0.357 +10^9/L,%,labs_neutrophil,labs_neutrophil_units, +C,F,vital_highesttem,vital_highesttem_units,1.8 +umol/L,mg/dL,labs_bilirubin,labs_bilirubin_units,17.1 +10^9/L,%,labs_lymphocyte,labs_lymphocyte_units, +"Fraction, 0.21-1.0","%, 21-100",vital_fio2spo2,vital_fio2spo2_units,100.0 +mg,mmol/L,labs_lactate,labs_lactate_units,0.0555 +mEq/L,mmol/L,labs_hco3,labs_hco3_units,1.0 +L/L,%,labs_hematocrit,labs_hematocrit_units,100.0 +mg/dL,ng/mL,labs_tropi,labs_tropi_units,10000.0 +mmol/L,Not done,comor_hba1c,comor_hba1c_units,1.0 +g/L,g/dL,labs_haemo,labs_haemo_units,10.0 diff --git a/tests/unit/assets/countries.csv b/tests/unit/assets/countries.csv new file mode 100644 index 0000000..cc83a7a --- /dev/null +++ b/tests/unit/assets/countries.csv @@ -0,0 +1,219 @@ +Country,Code,Region,Income group +Aruba,ABW,Latin America & Caribbean,High income +Afghanistan,AFG,South Asia,Low income +Angola,AGO,Sub-Saharan Africa,Lower middle income +Albania,ALB,Europe & Central Asia,Upper middle income +Andorra,AND,Europe & Central Asia,High income +United Arab Emirates,ARE,Middle East & North Africa,High income +Argentina,ARG,Latin America & Caribbean,Upper middle income +Armenia,ARM,Europe & Central Asia,Upper middle income +American Samoa,ASM,East Asia & Pacific,High income +Antigua and Barbuda,ATG,Latin America & Caribbean,High income +Australia,AUS,East Asia & Pacific,High income +Austria,AUT,Europe & Central Asia,High income +Azerbaijan,AZE,Europe & Central Asia,Upper middle income +Burundi,BDI,Sub-Saharan Africa,Low income +Belgium,BEL,Europe & Central Asia,High income +Benin,BEN,Sub-Saharan Africa,Lower middle income +Burkina Faso,BFA,Sub-Saharan Africa,Low income +Bangladesh,BGD,South Asia,Lower middle income +Bulgaria,BGR,Europe & Central Asia,Upper middle income +Bahrain,BHR,Middle East & North Africa,High income +"Bahamas, The",BHS,Latin America & Caribbean,High income +Bosnia and Herzegovina,BIH,Europe & Central Asia,Upper middle income +Belarus,BLR,Europe & Central Asia,Upper middle income +Belize,BLZ,Latin America & Caribbean,Upper middle income +Bermuda,BMU,North America,High income +Bolivia,BOL,Latin America & Caribbean,Lower middle income +Brazil,BRA,Latin America & Caribbean,Upper middle income +Barbados,BRB,Latin America & Caribbean,High income +Brunei Darussalam,BRN,East Asia & Pacific,High income +Bhutan,BTN,South Asia,Lower middle income +Botswana,BWA,Sub-Saharan Africa,Upper middle income +Central African Republic,CAF,Sub-Saharan Africa,Low income +Canada,CAN,North America,High income +Switzerland,CHE,Europe & Central Asia,High income +Channel Islands,CHI,Europe & Central Asia,High income +Chile,CHL,Latin America & Caribbean,High income +China,CHN,East Asia & Pacific,Upper middle income +Côte d’Ivoire,CIV,Sub-Saharan Africa,Lower middle income +Cameroon,CMR,Sub-Saharan Africa,Lower middle income +"Congo, Dem. Rep.",COD,Sub-Saharan Africa,Low income +"Congo, Rep.",COG,Sub-Saharan Africa,Lower middle income +Colombia,COL,Latin America & Caribbean,Upper middle income +Comoros,COM,Sub-Saharan Africa,Lower middle income +Cabo Verde,CPV,Sub-Saharan Africa,Lower middle income +Costa Rica,CRI,Latin America & Caribbean,Upper middle income +Cuba,CUB,Latin America & Caribbean,Upper middle income +Curaçao,CUW,Latin America & Caribbean,High income +Cayman Islands,CYM,Latin America & Caribbean,High income +Cyprus,CYP,Europe & Central Asia,High income +Czechia,CZE,Europe & Central Asia,High income +Germany,DEU,Europe & Central Asia,High income +Djibouti,DJI,Middle East & North Africa,Lower middle income +Dominica,DMA,Latin America & Caribbean,Upper middle income +Denmark,DNK,Europe & Central Asia,High income +Dominican Republic,DOM,Latin America & Caribbean,Upper middle income +Algeria,DZA,Middle East & North Africa,Lower middle income +Ecuador,ECU,Latin America & Caribbean,Upper middle income +"Egypt, Arab Rep.",EGY,Middle East & North Africa,Lower middle income +Eritrea,ERI,Sub-Saharan Africa,Low income +Spain,ESP,Europe & Central Asia,High income +Estonia,EST,Europe & Central Asia,High income +Ethiopia,ETH,Sub-Saharan Africa,Low income +Finland,FIN,Europe & Central Asia,High income +Fiji,FJI,East Asia & Pacific,Upper middle income +France,FRA,Europe & Central Asia,High income +Faroe Islands,FRO,Europe & Central Asia,High income +"Micronesia, Fed. Sts.",FSM,East Asia & Pacific,Lower middle income +Gabon,GAB,Sub-Saharan Africa,Upper middle income +United Kingdom,GBR,Europe & Central Asia,High income +Georgia,GEO,Europe & Central Asia,Upper middle income +Ghana,GHA,Sub-Saharan Africa,Lower middle income +Gibraltar,GIB,Europe & Central Asia,High income +Guinea,GIN,Sub-Saharan Africa,Lower middle income +"Gambia, The",GMB,Sub-Saharan Africa,Low income +Guinea-Bissau,GNB,Sub-Saharan Africa,Low income +Equatorial Guinea,GNQ,Sub-Saharan Africa,Upper middle income +Greece,GRC,Europe & Central Asia,High income +Grenada,GRD,Latin America & Caribbean,Upper middle income +Greenland,GRL,Europe & Central Asia,High income +Guatemala,GTM,Latin America & Caribbean,Upper middle income +Guam,GUM,East Asia & Pacific,High income +Guyana,GUY,Latin America & Caribbean,High income +"Hong Kong SAR, China",HKG,East Asia & Pacific,High income +Honduras,HND,Latin America & Caribbean,Lower middle income +Croatia,HRV,Europe & Central Asia,High income +Haiti,HTI,Latin America & Caribbean,Lower middle income +Hungary,HUN,Europe & Central Asia,High income +Indonesia,IDN,East Asia & Pacific,Upper middle income +Isle of Man,IMN,Europe & Central Asia,High income +India,IND,South Asia,Lower middle income +Ireland,IRL,Europe & Central Asia,High income +"Iran, Islamic Rep.",IRN,Middle East & North Africa,Lower middle income +Iraq,IRQ,Middle East & North Africa,Upper middle income +Iceland,ISL,Europe & Central Asia,High income +Israel,ISR,Middle East & North Africa,High income +Italy,ITA,Europe & Central Asia,High income +Jamaica,JAM,Latin America & Caribbean,Upper middle income +Jordan,JOR,Middle East & North Africa,Lower middle income +Japan,JPN,East Asia & Pacific,High income +Kazakhstan,KAZ,Europe & Central Asia,Upper middle income +Kenya,KEN,Sub-Saharan Africa,Lower middle income +Kyrgyz Republic,KGZ,Europe & Central Asia,Lower middle income +Cambodia,KHM,East Asia & Pacific,Lower middle income +Kiribati,KIR,East Asia & Pacific,Lower middle income +St. Kitts and Nevis,KNA,Latin America & Caribbean,High income +"Korea, Rep.",KOR,East Asia & Pacific,High income +Kuwait,KWT,Middle East & North Africa,High income +Lao PDR,LAO,East Asia & Pacific,Lower middle income +Lebanon,LBN,Middle East & North Africa,Lower middle income +Liberia,LBR,Sub-Saharan Africa,Low income +Libya,LBY,Middle East & North Africa,Upper middle income +St. Lucia,LCA,Latin America & Caribbean,Upper middle income +Liechtenstein,LIE,Europe & Central Asia,High income +Sri Lanka,LKA,South Asia,Lower middle income +Lesotho,LSO,Sub-Saharan Africa,Lower middle income +Lithuania,LTU,Europe & Central Asia,High income +Luxembourg,LUX,Europe & Central Asia,High income +Latvia,LVA,Europe & Central Asia,High income +"Macao SAR, China",MAC,East Asia & Pacific,High income +St. Martin (French part),MAF,Latin America & Caribbean,High income +Morocco,MAR,Middle East & North Africa,Lower middle income +Monaco,MCO,Europe & Central Asia,High income +Moldova,MDA,Europe & Central Asia,Upper middle income +Madagascar,MDG,Sub-Saharan Africa,Low income +Maldives,MDV,South Asia,Upper middle income +Mexico,MEX,Latin America & Caribbean,Upper middle income +Marshall Islands,MHL,East Asia & Pacific,Upper middle income +North Macedonia,MKD,Europe & Central Asia,Upper middle income +Mali,MLI,Sub-Saharan Africa,Low income +Malta,MLT,Middle East & North Africa,High income +Myanmar,MMR,East Asia & Pacific,Lower middle income +Montenegro,MNE,Europe & Central Asia,Upper middle income +Mongolia,MNG,East Asia & Pacific,Lower middle income +Northern Mariana Islands,MNP,East Asia & Pacific,High income +Mozambique,MOZ,Sub-Saharan Africa,Low income +Mauritania,MRT,Sub-Saharan Africa,Lower middle income +Mauritius,MUS,Sub-Saharan Africa,Upper middle income +Malawi,MWI,Sub-Saharan Africa,Low income +Malaysia,MYS,East Asia & Pacific,Upper middle income +Namibia,NAM,Sub-Saharan Africa,Upper middle income +New Caledonia,NCL,East Asia & Pacific,High income +Niger,NER,Sub-Saharan Africa,Low income +Nigeria,NGA,Sub-Saharan Africa,Lower middle income +Nicaragua,NIC,Latin America & Caribbean,Lower middle income +Netherlands,NLD,Europe & Central Asia,High income +Norway,NOR,Europe & Central Asia,High income +Nepal,NPL,South Asia,Lower middle income +Nauru,NRU,East Asia & Pacific,High income +New Zealand,NZL,East Asia & Pacific,High income +Oman,OMN,Middle East & North Africa,High income +Pakistan,PAK,South Asia,Lower middle income +Panama,PAN,Latin America & Caribbean,High income +Peru,PER,Latin America & Caribbean,Upper middle income +Philippines,PHL,East Asia & Pacific,Lower middle income +Palau,PLW,East Asia & Pacific,Upper middle income +Papua New Guinea,PNG,East Asia & Pacific,Lower middle income +Poland,POL,Europe & Central Asia,High income +Puerto Rico,PRI,Latin America & Caribbean,High income +"Korea, Dem. People's Rep.",PRK,East Asia & Pacific,Low income +Portugal,PRT,Europe & Central Asia,High income +Paraguay,PRY,Latin America & Caribbean,Upper middle income +West Bank and Gaza,PSE,Middle East & North Africa,Upper middle income +French Polynesia,PYF,East Asia & Pacific,High income +Qatar,QAT,Middle East & North Africa,High income +Romania,ROU,Europe & Central Asia,High income +Russian Federation,RUS,Europe & Central Asia,Upper middle income +Rwanda,RWA,Sub-Saharan Africa,Low income +Saudi Arabia,SAU,Middle East & North Africa,High income +Sudan,SDN,Sub-Saharan Africa,Low income +Senegal,SEN,Sub-Saharan Africa,Lower middle income +Singapore,SGP,East Asia & Pacific,High income +Solomon Islands,SLB,East Asia & Pacific,Lower middle income +Sierra Leone,SLE,Sub-Saharan Africa,Low income +El Salvador,SLV,Latin America & Caribbean,Upper middle income +San Marino,SMR,Europe & Central Asia,High income +Somalia,SOM,Sub-Saharan Africa,Low income +Serbia,SRB,Europe & Central Asia,Upper middle income +South Sudan,SSD,Sub-Saharan Africa,Low income +São Tomé and Príncipe,STP,Sub-Saharan Africa,Lower middle income +Suriname,SUR,Latin America & Caribbean,Upper middle income +Slovak Republic,SVK,Europe & Central Asia,High income +Slovenia,SVN,Europe & Central Asia,High income +Sweden,SWE,Europe & Central Asia,High income +Eswatini,SWZ,Sub-Saharan Africa,Lower middle income +Sint Maarten (Dutch part),SXM,Latin America & Caribbean,High income +Seychelles,SYC,Sub-Saharan Africa,High income +Syrian Arab Republic,SYR,Middle East & North Africa,Low income +Turks and Caicos Islands,TCA,Latin America & Caribbean,High income +Chad,TCD,Sub-Saharan Africa,Low income +Togo,TGO,Sub-Saharan Africa,Low income +Thailand,THA,East Asia & Pacific,Upper middle income +Tajikistan,TJK,Europe & Central Asia,Lower middle income +Turkmenistan,TKM,Europe & Central Asia,Upper middle income +Timor-Leste,TLS,East Asia & Pacific,Lower middle income +Tonga,TON,East Asia & Pacific,Upper middle income +Trinidad and Tobago,TTO,Latin America & Caribbean,High income +Tunisia,TUN,Middle East & North Africa,Lower middle income +Türkiye,TUR,Europe & Central Asia,Upper middle income +Tuvalu,TUV,East Asia & Pacific,Upper middle income +"Taiwan, China",TWN,East Asia & Pacific,High income +Tanzania,TZA,Sub-Saharan Africa,Lower middle income +Uganda,UGA,Sub-Saharan Africa,Low income +Ukraine,UKR,Europe & Central Asia,Lower middle income +Uruguay,URY,Latin America & Caribbean,High income +United States,USA,North America,High income +Uzbekistan,UZB,Europe & Central Asia,Lower middle income +St. Vincent and the Grenadines,VCT,Latin America & Caribbean,Upper middle income +"Venezuela, RB",VEN,Latin America & Caribbean, +British Virgin Islands,VGB,Latin America & Caribbean,High income +Virgin Islands (U.S.),VIR,Latin America & Caribbean,High income +Vietnam,VNM,East Asia & Pacific,Lower middle income +Vanuatu,VUT,East Asia & Pacific,Lower middle income +Samoa,WSM,East Asia & Pacific,Lower middle income +Kosovo,XKX,Europe & Central Asia,Upper middle income +"Yemen, Rep.",YEM,Middle East & North Africa,Low income +South Africa,ZAF,Sub-Saharan Africa,Upper middle income +Zambia,ZMB,Sub-Saharan Africa,Lower middle income +Zimbabwe,ZWE,Sub-Saharan Africa,Lower middle income diff --git a/tests/unit/test_redcap_data.py b/tests/unit/test_redcap_data.py new file mode 100644 index 0000000..aa261ed --- /dev/null +++ b/tests/unit/test_redcap_data.py @@ -0,0 +1,90 @@ +# -- IMPORTS -- + +# -- Standard libraries -- +import unittest.mock as mock +from pathlib import Path + +# -- 3rd party libraries -- +import pandas as pd +from pandas.testing import assert_frame_equal + +# -- Internal libraries -- +from isaricanalytics.redcap_data import ( + load_countries_table, + load_units_conversion_table, +) + + +class TestLoadUnitsConversionTable: + def test_load_units_conversion_table__from_local_assets(self): + with Path(__file__).parent.parent.parent.joinpath( + "assets", "conversion_table.csv" + ) as local_assets_csv_path: + expected_table = pd.read_csv( + Path(__file__).parent.joinpath("assets", "conversion_table.csv") + ) + + with mock.patch( + "isaricanalytics.redcap_data.pd.read_csv", + mock.MagicMock(return_value=expected_table), + ) as mock_pd_read_csv: + received_table = load_units_conversion_table() + mock_pd_read_csv.assert_called_once_with(local_assets_csv_path) + assert_frame_equal(received_table, expected_table) + + def test_load_units_conversion_table__from_vertex_github(self): + with mock.patch( + "isaricanalytics.redcap_data.Path", side_effect=FileNotFoundError + ): + expected_table = pd.read_csv( + Path(__file__).parent.joinpath("assets", "conversion_table.csv") + ) + + with mock.patch( + "isaricanalytics.redcap_data.pd.read_csv", + mock.MagicMock(return_value=expected_table), + ) as mock_pd_read_csv: + received_table = load_units_conversion_table() + mock_pd_read_csv.assert_called_once_with( + "https://raw.githubusercontent.com/ISARICResearch/VERTEX/refs/heads/main/assets/conversion_table.csv" + ) + assert_frame_equal(received_table, expected_table) + + +class TestLoadCountriesTable: + def test_load_countries_table__from_local_assets(self): + with Path(__file__).parent.parent.parent.joinpath( + "assets", "countries.csv" + ) as local_assets_csv_path: + expected_table = pd.read_csv( + Path(__file__).parent.joinpath("assets", "countries.csv") + ) + + with mock.patch( + "isaricanalytics.redcap_data.pd.read_csv", + mock.MagicMock(return_value=expected_table), + ) as mock_pd_read_csv: + received_table = load_countries_table(encoding="latin-1") + mock_pd_read_csv.assert_called_once_with( + local_assets_csv_path, encoding="latin-1" + ) + assert_frame_equal(received_table, expected_table) + + def test_load_countries_table__from_vertex_github(self): + with mock.patch( + "isaricanalytics.redcap_data.Path", side_effect=FileNotFoundError + ): + expected_table = pd.read_csv( + Path(__file__).parent.joinpath("assets", "countries.csv") + ) + + with mock.patch( + "isaricanalytics.redcap_data.pd.read_csv", + mock.MagicMock(return_value=expected_table), + ) as mock_pd_read_csv: + received_table = load_countries_table(encoding="latin-1") + mock_pd_read_csv.assert_called_once_with( + "https://raw.githubusercontent.com/ISARICResearch/VERTEX/refs/heads/main/assets/countries.csv", + encoding="latin-1", + ) + assert_frame_equal(received_table, expected_table) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py new file mode 100644 index 0000000..8af465d --- /dev/null +++ b/tests/unit/test_utils.py @@ -0,0 +1,39 @@ +# -- IMPORTS -- + +# -- Standard libraries -- + +# -- 3rd party libraries -- +import pytest + +# -- Internal libraries -- +from isaricanalytics.utils import ( + strip_html, + strip_nonstandard_unicode_chars, +) + + +@pytest.mark.parametrize( + ("value", "expected"), + [ + (-1, -1), + (True, True), + ("Value", "Value"), + ("Value", "Value"), + ], +) +def test_strip_html(value, expected): + assert strip_html(value) == expected + + +@pytest.mark.parametrize( + ("value", "expected"), + [ + (-1, -1), + (True, True), + ("Value", "Value"), + ("Value", "Value"), + ("↳ Value", " Value"), + ], +) +def test_strip_nonstandard_unicode_chars(value, expected): + assert strip_nonstandard_unicode_chars(value) == expected diff --git a/tests/unit/test_visualisation.py b/tests/unit/test_visualisation.py new file mode 100644 index 0000000..056b7a6 --- /dev/null +++ b/tests/unit/test_visualisation.py @@ -0,0 +1,833 @@ +# -- IMPORTS -- + +# -- Standard libraries -- + +# -- 3rd party libraries -- +import pandas as pd +import plotly.graph_objs as go +import pytest +from numpy.testing import assert_array_equal + +# -- Internal libraries -- +from isaricanalytics.utils import strip_html +from isaricanalytics.visualisation import ( + fig_bar_chart, + fig_count_chart, + fig_dual_stack_pyramid, + fig_forest_plot, + fig_frequency_chart, + fig_kaplan_meier, + fig_pie, + fig_placeholder, + fig_sunburst, + fig_table, + fig_timelines, + hex_to_rgb, + hex_to_rgba, + rgb_to_rgba, +) + + +class TestFigBarChart: + def test_fig_bar_chart(self): + data_in = pd.DataFrame().assign( + time=["06:00", "09:00", "12:00", "15:00", "18:00", "21:00"], + temperature=[12.0, 15.5, 18.9, 20.2, 18.5, 15.8], + ) + fig_out = fig_bar_chart( + data_in, + title="Test bar chart - time vs temperature (Celsius)", + xlabel="Time of day", + ylabel="Temperature (Celsius)", + index_column="time", + height=340, + ) + + assert isinstance(fig_out, go.Figure) + assert ( + fig_out.layout.title.text + == "Test bar chart - time vs temperature (Celsius)" + ) + assert fig_out.layout.height == 340 + assert isinstance(fig_out.data[0], go._bar.Bar) + assert_array_equal(fig_out.data[0].x, data_in["time"].values) + assert_array_equal(fig_out.data[0].y, data_in["temperature"].values) + + +class TestFigCountChart: + def test_fig_count_chart(self): + data_in = pd.DataFrame().assign( + label=["Mathematics", "Economics", "Physics", "Physiology or Medicine"], + count=[2, 3, 2, 3], + short_label=[ + "Mathematics", + "Economics", + "Physics", + "Physiology or Medicine", + ], + ) + fig_out = fig_count_chart( + data_in, + title="Test count chart - students by major field", + xlabel="Count", + ylabel="Student Major Field", + height=350, + ) + + assert isinstance(fig_out, go.Figure) + assert fig_out.layout.title.text == "Test count chart - students by major field" + assert fig_out.layout.height == 350 + assert len(fig_out.data) == 4 + assert all(isinstance(data_item, go._bar.Bar) for data_item in fig_out.data) + + +class TestFigDualStackedPyramid: + def test_fig_dual_stack_pyramid(self): + # Test data taken from the dual stacked pyramid chart in the Dengue + # demo project with synthetic data. + data_in = pd.DataFrame( + columns=["side", "y_axis", "stack_group", "value", "left_side"], + data=[ + ["Female", "0-5", "Censored", 2, True], + ["Female", "0-5", "Death", 1, True], + ["Female", "0-5", "Discharged", 3, True], + ["Male", "0-5", "Death", 13, False], + ["Male", "0-5", "Censored", 18, False], + ["Male", "0-5", "Discharged", 12, False], + ["Male", "6-10", "Death", 5, False], + ["Male", "6-10", "Discharged", 2, False], + ["Male", "6-10", "Censored", 5, False], + ["Female", "6-10", "Censored", 3, True], + ["Female", "6-10", "Death", 1, True], + ["Male", "11-15", "Censored", 2, False], + ["Male", "11-15", "Death", 3, False], + ["Male", "16-20", "Death", 1, False], + ["Female", "16-20", "Censored", 1, True], + ["Female", "16-20", "Discharged", 1, True], + ["Female", "16-20", "Death", 1, True], + ["Male", "16-20", "Discharged", 1, False], + ["Male", "16-20", "Censored", 4, False], + ["Male", "21-25", "Death", 2, False], + ["Male", "21-25", "Censored", 1, False], + ["Female", "26-30", "Discharged", 1, True], + ["Male", "26-30", "Censored", 6, False], + ["Male", "26-30", "Discharged", 4, False], + ["Female", "26-30", "Censored", 1, True], + ["Male", "26-30", "Death", 2, False], + ["Male", "31-35", "Death", 2, False], + ["Male", "31-35", "Discharged", 3, False], + ["Male", "31-35", "Censored", 3, False], + ["Male", "36-40", "Discharged", 2, False], + ["Male", "36-40", "Death", 1, False], + ["Male", "36-40", "Censored", 4, False], + ["Female", "36-40", "Censored", 1, True], + ["Female", "36-40", "Death", 1, True], + ["Female", "36-40", "Discharged", 1, True], + ["Female", "41-45", "Censored", 1, True], + ["Male", "41-45", "Censored", 5, False], + ["Male", "41-45", "Death", 1, False], + ["Male", "41-45", "Discharged", 3, False], + ["Male", "46-50", "Censored", 5, False], + ["Male", "46-50", "Death", 4, False], + ["Male", "46-50", "Discharged", 4, False], + ["Female", "46-50", "Censored", 1, True], + ["Female", "51-55", "Censored", 1, True], + ["Male", "51-55", "Death", 1, False], + ["Male", "51-55", "Discharged", 2, False], + ["Male", "51-55", "Censored", 1, False], + ["Male", "56-60", "Death", 1, False], + ["Male", "56-60", "Discharged", 4, False], + ["Male", "56-60", "Censored", 3, False], + ["Female", "56-60", "Death", 1, True], + ["Female", "61-65", "Censored", 1, True], + ["Male", "61-65", "Discharged", 2, False], + ["Male", "61-65", "Death", 4, False], + ["Male", "61-65", "Censored", 5, False], + ["Male", "66-70", "Discharged", 2, False], + ["Male", "66-70", "Censored", 5, False], + ["Male", "66-70", "Death", 2, False], + ["Female", "66-70", "Discharged", 1, True], + ["Male", "71-75", "Discharged", 1, False], + ["Female", "71-75", "Death", 1, True], + ["Male", "71-75", "Censored", 3, False], + ["Male", "71-75", "Death", 1, False], + ["Male", "76-80", "Discharged", 1, False], + ["Male", "76-80", "Death", 1, False], + ["Male", "76-80", "Censored", 3, False], + ["Female", "76-80", "Censored", 1, True], + ["Male", "81-85", "Censored", 6, False], + ["Male", "81-85", "Death", 2, False], + ["Male", "81-85", "Discharged", 1, False], + ["Female", "81-85", "Death", 2, True], + ["Male", "86-90", "Death", 2, False], + ["Male", "86-90", "Censored", 7, False], + ["Male", "86-90", "Discharged", 2, False], + ["Male", "91-95", "Discharged", 1, False], + ["Male", "91-95", "Death", 2, False], + ["Female", "91-95", "Censored", 1, True], + ["Female", "91-95", "Death", 1, True], + ["Male", "91-95", "Censored", 3, False], + ["Male", "96-100", "Death", 2, False], + ["Male", "96-100", "Censored", 3, False], + ["Male", "96-100", "Discharged", 2, False], + ], + ) + fig_out = fig_dual_stack_pyramid( + data_in, + title=( + "Test dual-sided population pyramid chart - " + "showing age, sex and outcome" + ), + ylabel="Age Group", + base_color_map={ + "Discharged": "#00C26F", + "Censored": "#FFF500", + "Death": "#DF0069", + }, + height=430, + ) + + assert isinstance(fig_out, go.Figure) + assert ( + fig_out.layout.title.text + == "Test dual-sided population pyramid chart - showing age, sex and outcome" + ) + assert fig_out.layout.height == 430 + + # Bar charts for the no. of combinations of sex and outcome = 2 x 3 = 6 + assert len(fig_out.data) == 6 + assert all(isinstance(data_item, go._bar.Bar) for data_item in fig_out.data) + + +class TestFigForestPlot: + def test_fig_forest_plot(self): + data_in = pd.DataFrame( + columns=[ + "Variable", + "OddsRatio (multi)", + "LowerCI (multi)", + "UpperCI (multi)", + "p-value (multi)", + ], + data=[ + ["Sex at birth, Male", 1.949, 1.149, 3.307, 0.0134], + ["Age", 1.01, 0.998, 1.021, 0.1012], + [ + "Type of liver disease, Moderate or severe", + 0.584, + 0.183, + 1.864, + 0.3642, + ], + ["Obesity", 1.181, 0.679, 2.054, 0.555], + ["Hypertension (physician diagnosed)", 2.399, 1.431, 4.022, 0.0009], + [ + "Vaccinated for seasonal influenza (ever)", + 1.644, + 0.98, + 2.758, + 0.0594, + ], + ["Fever", 1.379, 0.766, 2.484, 0.2841], + ["Headache", 0.787, 0.469, 1.32, 0.3634], + [ + "Glasgow Coma Score (GCS / 15), Moderate (9 to 11)", + 1.801, + 0.96, + 3.38, + 0.0669, + ], + [ + "Glasgow Coma Score (GCS / 15), Severe (less than 9)", + 2.878, + 1.526, + 5.426, + 0.0011, + ], + ["Platelets (10^3/uL), Low (under 1.5)", 1.536, 0.706, 3.339, 0.2789], + ["Platelets (10^3/uL), High (over 4.5)", 4.741, 1.336, 16.829, 0.016], + ["Employed as a healthcare worker", 0.644, 0.309, 1.341, 0.2398], + ["Ever smoked", 1.53, 0.842, 2.781, 0.1631], + ["Diabetes mellitus", 2.174, 1.231, 3.838, 0.0074], + [ + "Stage of chronic kidney disease, Stage 1", + 1.607, + 0.427, + 6.048, + 0.4833, + ], + [ + "Stage of chronic kidney disease, Stage 2", + 0.627, + 0.194, + 2.021, + 0.4339, + ], + [ + "Stage of chronic kidney disease, Stage 3a", + 0.895, + 0.281, + 2.852, + 0.8507, + ], + [ + "Stage of chronic kidney disease, Stage 3b or 4 or 5", + 1.798, + 0.485, + 6.674, + 0.3803, + ], + ["Type of liver disease, Mild", 2.089, 0.975, 4.473, 0.058], + ], + ) + fig_out = fig_forest_plot( + data_in, + title="Test forest plot - anytime in-hospital mortality", + xlabel="Odds Ratio (95% CI)", + ylabel="", + labels=[ + "Variable", + "OddsRatio (multi)", + "LowerCI (multi)", + "UpperCI (multi)", + "p-value (multi)", + ], + height=600, + ) + + assert isinstance(fig_out, go.Figure) + assert ( + fig_out.layout.title.text + == "Test forest plot - anytime in-hospital mortality" + ) + assert fig_out.layout.xaxis.title.text == "Odds Ratio (95% CI)" + assert fig_out.layout.height == 600 + assert len(fig_out.data) == 21 + assert all( + isinstance(data_item, go._scatter.Scatter) for data_item in fig_out.data + ) + assert set(fig_out.data[0].x) == set(data_in["OddsRatio (multi)"]) + assert set(fig_out.data[0].y) == set(data_in["Variable"]) + + +class TestFigFrequencyChart: + def test_fig_frequency_chart(self): + data_in = pd.DataFrame().assign( + label=["Mathematics", "Economics", "Physics", "Physiology or Medicine"], + proportion=[0.3, 0.15, 0.1, 0.45], + short_label=[ + "Mathematics", + "Economics", + "Physics", + "Physiology or Medicine", + ], + ) + fig_out = fig_frequency_chart( + data_in, + title="Test frequency chart - student majors by field", + xlabel="Percentage", + ylabel="Student Major Field", + height=350, + ) + + assert isinstance(fig_out, go.Figure) + assert ( + fig_out.layout.title.text + == "Test frequency chart - student majors by field" + ) + assert fig_out.layout.height == 350 + assert len(fig_out.data) == 8 + assert all(isinstance(data_item, go._bar.Bar) for data_item in fig_out.data) + + +class TestFigKaplanMeier: + def test_fig_kaplan_meier(self): + km_data_in = pd.DataFrame( + columns=[ + "timeline", + "0-39", + "0-39_lower_0.95", + "0-39_upper_0.95", + "40-64", + "40-64_lower_0.95", + "40-64_upper_0.95", + ">64", + ">64_lower_0.95", + ">64_upper_0.95", + ], + data=[ + [0.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0], + [ + 3.0, + 98.18181818181826, + 96.39735054616156, + 99.08657016907878, + 99.55752212389378, + 96.90088134700424, + 99.93755232321789, + 98.81889763779525, + 96.38311787603637, + 99.61753753722978, + ], + [ + 4.0, + 98.18181818181826, + 96.39735054616156, + 99.08657016907878, + 98.89820078532492, + 95.54952547737416, + 99.73073978542168, + 98.81889763779525, + 96.38311787603637, + 99.61753753722978, + ], + [ + 5.0, + 95.36768963520568, + 92.60698242810584, + 97.11347866289374, + 98.89820078532492, + 95.54952547737416, + 99.73073978542168, + 98.81889763779525, + 96.38311787603637, + 99.61753753722978, + ], + [ + 6.0, + 94.42810648609036, + 91.27618131269512, + 96.46318369215324, + 97.999126232731, + 93.65495711588476, + 99.37876135264092, + 97.948246557286, + 95.13505854819972, + 99.14196321338244, + ], + [ + 7.0, + 91.84103507551256, + 87.53090853993217, + 94.7060430396404, + 96.7096640454582, + 90.86213734535134, + 98.8386876127919, + 94.94983084634872, + 91.034097752017, + 97.18164888548608, + ], + [ + 8.0, + 84.61758287856217, + 77.37293717865721, + 89.6953188510786, + 92.59435919245998, + 82.6454677155429, + 96.94188674506084, + 90.42841032985592, + 85.10140816062759, + 93.91813320008492, + ], + [ + 9.0, + 76.15582459070596, + 65.80771668823222, + 83.75137248761123, + 89.16493848162813, + 75.70020536177844, + 95.385530380624, + 87.01601748721983, + 80.64628925994477, + 91.3999519629908, + ], + [ + 10.0, + 66.22245616583126, + 51.45905617744299, + 77.43915318100328, + 72.44651251632285, + 48.96117462409049, + 86.46098576504949, + 82.3751632212348, + 74.49383017790512, + 88.01469585065641, + ], + [ + 11.0, + 52.97796493266499, + 32.231842991966055, + 70.01448228633087, + 63.39069845178251, + 36.1082330026806, + 81.54643352355325, + 77.11717407945385, + 67.23047069641812, + 84.36189542328422, + ], + [ + 12.0, + None, + None, + None, + None, + None, + None, + 69.13953538157931, + 56.100461856710325, + 79.0082809666679, + ], + [ + 13.0, + None, + None, + None, + None, + None, + None, + 61.00547239551115, + 44.7978150272324, + 73.77461192167068, + ], + [ + 14.0, + None, + None, + None, + None, + None, + None, + 47.44870075206421, + 26.8197019105621, + 65.55170703215035, + ], + [ + 15.0, + None, + None, + None, + None, + None, + None, + 37.95896060165138, + 16.243468770788308, + 59.67418998689532, + ], + ], + ) + risktable_data_in = pd.DataFrame( + columns=["Group", "0", "5", "10", "15"], + data=[ + ["0-39", 512, 314, 23, 0], + ["40-64", 233, 151, 16, 0], + [">64", 255, 254, 75, 5], + ], + ) + + fig_out = fig_kaplan_meier( + (km_data_in, risktable_data_in), + title="Test Kaplan-Meier plot - in-hospital mortality", + xlabel="Time (days)", + ylabel="Survival Probability", + index_column="Group", + p_value=0.004799680324617032, + height=480, + ) + + assert isinstance(fig_out, go.Figure) + assert ( + fig_out.layout.annotations[0].text + == "Test Kaplan-Meier plot - in-hospital mortality" + ) + assert fig_out.layout.xaxis.title.text == "Time (days)" + assert fig_out.layout.yaxis.title.text == "Survival Probability" + assert fig_out.layout.height == 480 + + +class TestFigPie: + def test_fig_pie(self): + data_in = pd.DataFrame().assign( + country=["Country A", "Country B", "Country C", "Country D", "Country E"], + population=[10000000, 2000000, 5000000, 12000000, 1000000], + ) + fig_out = fig_pie( + data_in, + title="Test pie chart - countries and populations", + xlabel="", + ylabel="", + base_color_map={ + 10000000: "maroon", + 12000000: "red", + 1000000: "pink", + 2000000: "green", + 5000000: "yellow", + }, + names=data_in["country"], + values=data_in["population"], + height=450, + ) + + assert isinstance(fig_out, go.Figure) + assert fig_out.layout.title.text == "Test pie chart - countries and populations" + assert fig_out.layout.height == 450 + assert isinstance(fig_out.data[0], go._pie.Pie) + assert_array_equal(fig_out.data[0].labels, data_in["country"]) + assert_array_equal(fig_out.data[0].values, data_in["population"]) + + +class TestFigPlaceholder: + def test_fig_placeholder__no_data(self): + fig_out = fig_placeholder( + None, + title="Test placeholder scatter plot - no data", + xlabel="x", + ylabel="y", + height=450, + ) + + assert isinstance(fig_out, go.Figure) + assert fig_out.layout.title.text == "Test placeholder scatter plot - no data" + assert fig_out.layout.xaxis.title.text == "x" + assert fig_out.layout.yaxis.title.text == "y" + assert fig_out.layout.height == 450 + assert isinstance(fig_out.data[0], go._scatter.Scatter) + assert_array_equal(fig_out.data[0].x, [1, 2, 3, 4, 5]) + assert len(fig_out.data[0].y) == 5 + assert min(fig_out.data[0].y) >= 10 + assert max(fig_out.data[0].y) <= 15 + + def test_fig_placeholder__custom_data(self): + data_in = pd.DataFrame().assign(x=[1, 2, 3, 4, 5], y=[1, 4, 9, 16, 25]) + fig_out = fig_placeholder( + data_in, + title="Test placeholder scatter plot - custom data", + xlabel="x", + ylabel="y", + height=450, + ) + + assert isinstance(fig_out, go.Figure) + assert ( + fig_out.layout.title.text == "Test placeholder scatter plot - custom data" + ) + assert fig_out.layout.xaxis.title.text == "x" + assert fig_out.layout.yaxis.title.text == "y" + assert fig_out.layout.height == 450 + assert isinstance(fig_out.data[0], go._scatter.Scatter) + assert_array_equal(fig_out.data[0].x, data_in["x"]) + assert_array_equal(fig_out.data[0].y, data_in["y"]) + + +class TestFigSunburst: + def test_fig_sunburst(self): + data_in = pd.DataFrame().assign( + total_bill=[16.99, 10.34, 21.01, 23.68, 24.59], + tip=[1.01, 1.66, 3.50, 3.31, 3.61], + sex=["Female", "Male", "Male", "Male", "Female"], + smoker=["No", "No", "No", "No", "No"], + day=["Sun", "Sat", "Fri", "Fri", "Sun"], + occasion=["Dinner", "Lunch", "Drinks", "Drinks", "Dinner"], + ) + fig_out = fig_sunburst( + data_in, + title="Test sunburst chart - restaurant bills by day, occasion, sex", + path=["day", "occasion", "sex"], + values="total_bill", + height=430, + ) + + assert isinstance(fig_out, go.Figure) + assert ( + fig_out.layout.title.text + == "Test sunburst chart - restaurant bills by day, occasion, sex" + ) + assert fig_out.layout.height == 430 + assert isinstance(fig_out.data[0], go._sunburst.Sunburst) + + +class TestFigTable: + def test_fig_table(self): + data_in = pd.DataFrame().assign( + A=["A1", "A2", "A3", "A4", "A5"], + B=["B1", "B2", "B3", "B4", "B5"], + C=["C1", "C2", "C3", "C4", "C5"], + ) + fig_out = fig_table( + data_in, + table_key="test_table_key", + columnwidth=[0.1] * 3, + height=500, + ) + + assert isinstance(fig_out, go.Figure) + assert fig_out.layout.title.text == "test_table_key" + assert fig_out.layout.height == 500 + assert isinstance(fig_out.data[0], go._table.Table) + assert_array_equal( + [strip_html(val) for val in fig_out.data[0].header.values], + data_in.columns.tolist(), + ) + for i, col in zip([0, 1, 2], ["A", "B", "C"]): + assert_array_equal(fig_out.data[0].cells.values[i], data_in[col].values) + + +class TestFigText: + def test_fig_text(self): + data_in = pd.DataFrame( + "Test disclaimer text", columns=["paragraphs"], index=range(1) + ) + fig_out = fig_table( + data_in, + height=430, + ) + + assert isinstance(fig_out, go.Figure) + assert fig_out.layout.height == 430 + assert isinstance(fig_out.data[0], go._table.Table) + assert fig_out.data[0].cells.values[0][0] == "Test disclaimer text" + + +class TestFigTimelines: + def test_fig_timelines__no_size_col(self): + data_in = pd.DataFrame().assign( + task=["Phase A", "Phase B", "Phase C"], + start=["2026-01-01", "2026-03-05", "2026-02-20"], + end=["2026-02-28", "2026-04-15", "2026-05-30"], + ) + # One task per group, vice versa + fig_out = fig_timelines( + data_in, + title="Test timelines plot - job phases", + label_col="task", + group_col="task", + start_date="start", + end_date="end", + size_col=None, + height=500, + ) + + assert isinstance(fig_out, go.Figure) + assert fig_out.layout.title.text == "Test timelines plot - job phases" + assert all( + isinstance(data_item, go._scatter.Scatter) for data_item in fig_out.data + ) + assert_array_equal([t.legendgroup for t in fig_out.data], data_in["task"]) + assert all( + isinstance(data_item, go._scatter.Scatter) for data_item in fig_out.data + ) + for i, task in enumerate(data_in["task"]): + assert ( + str(fig_out.data[i].x[0].date()) + == data_in[data_in["task"] == task]["start"].at[i] + ) + assert ( + str(fig_out.data[i].x[1].date()) + == data_in[data_in["task"] == task]["end"].at[i] + ) + + def test_fig_timelines__size_col(self): + data_in = pd.DataFrame().assign( + task=["Phase A", "Phase B", "Phase C"], + start=["2026-01-01", "2026-03-05", "2026-02-20"], + end=["2026-02-28", "2026-04-15", "2026-05-30"], + line_width=[2, 2.5, 4], + ) + # One task per group, vice versa + fig_out = fig_timelines( + data_in, + title="Test timelines plot - job phases", + label_col="task", + group_col="task", + start_date="start", + end_date="end", + size_col="line_width", + height=500, + ) + + assert isinstance(fig_out, go.Figure) + assert fig_out.layout.title.text == "Test timelines plot - job phases" + assert all( + isinstance(data_item, go._scatter.Scatter) for data_item in fig_out.data + ) + assert_array_equal([t.legendgroup for t in fig_out.data], data_in["task"]) + assert all( + isinstance(data_item, go._scatter.Scatter) for data_item in fig_out.data + ) + for i, task in enumerate(data_in["task"]): + assert ( + str(fig_out.data[i].x[0].date()) + == data_in[data_in["task"] == task]["start"].at[i] + ) + assert ( + str(fig_out.data[i].x[1].date()) + == data_in[data_in["task"] == task]["end"].at[i] + ) + + +class TestHexToRgb: + @pytest.mark.parametrize( + """hex_color, + expected_rgb_color""", + [ + ( + "#000000", + (0, 0, 0), + ), + ( + "#ffffff", + (255, 255, 255), + ), + ( + "#092227", + (9, 34, 39), + ), + ( + "#d9384b", + (217, 56, 75), + ), + ], + ) + def test_hex_to_rgb(self, hex_color, expected_rgb_color): + assert hex_to_rgb(hex_color) == expected_rgb_color + + +class TestHexToRgba: + @pytest.mark.parametrize( + """hex_color, + opacity, + expected_rgba_string""", + [ + ( + "#000000", + 0.0, + "rgba(0, 0, 0, 0.0)", + ), + ( + "#092227", + 0.5, + "rgba(9, 34, 39, 0.5)", + ), + ( + "#ffffff", + 1.0, + "rgba(255, 255, 255, 1.0)", + ), + ], + ) + def test_hex_to_rgba(self, hex_color, opacity, expected_rgba_string): + assert hex_to_rgba(hex_color, opacity) == expected_rgba_string + + +class TestRgbToRgba: + @pytest.mark.parametrize( + """rgb_color, + alpha, + expected_rgba_string""", + [ + ((0, 0, 0), 0.0, "rgba(0, 0, 0, 0.0)"), + ((9, 34, 39), 0.5, "rgba(9, 34, 39, 0.5)"), + ((255, 255, 255), 1.0, "rgba(255, 255, 255, 1.0)"), + ], + ) + def test_rgb_to_rgba(self, rgb_color, alpha, expected_rgba_string): + assert rgb_to_rgba(rgb_color, alpha) == expected_rgba_string From ff3df6635feea6a06f408afadb7b1cc1d9b981ce Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 1 May 2026 17:25:26 +0100 Subject: [PATCH 13/34] docs: add RTD YML + `docs/requirements.txt` --- .readthedocs.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 5b6161f..81805ec 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,7 +10,6 @@ build: os: ubuntu-lts-latest tools: python: "3.11" - # You can also specify other tool versions: # nodejs: "20" # rust: "1.70" From 03b1ba81be0d83901920289fe7a861c0632ab204 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Tue, 5 May 2026 15:00:37 +0100 Subject: [PATCH 14/34] style: docstrings and type hinting for core libs --- isaricanalytics/analytics.py | 2091 +++++++++++++++++++++++------- isaricanalytics/redcap_data.py | 987 +++++++++++--- isaricanalytics/visualisation.py | 2 + 3 files changed, 2440 insertions(+), 640 deletions(-) diff --git a/isaricanalytics/analytics.py b/isaricanalytics/analytics.py index 4c32974..621131c 100644 --- a/isaricanalytics/analytics.py +++ b/isaricanalytics/analytics.py @@ -1,5 +1,57 @@ +from __future__ import annotations + +__all__ = [ + "classification_report", + "convert_categorical_to_onehot", + "convert_onehot_to_categorical", + "create_grouped_results", + "descriptive_comparison_table", + "descriptive_table", + "execute_cox_model", + "execute_glm_regression", + "execute_glmm_regression", + "execute_kaplan_meier", + "extend_dictionary", + "format_descriptive_table_variables", + "format_pvalue", + "format_variables", + "from_timeA_to_timeB", + "get_chi2_pvalue", + "get_counts", + "get_descriptive_data", + "get_fisher_exact_pvalue", + "get_mean_and_stdev", + "get_median_interquartile_range", + "get_modelling_data", + "get_n_percent_value", + "get_parameter_ranking", + "get_proportions", + "get_pyramid_data", + "get_upset_counts_intersections", + "get_variables_by_section_and_type", + "impute_miss_val", + "lasso_var_sel_binary", + "mannwhitneyu", + "mean_std_str", + "median_iqr_str", + "n_percent_str", + "norm", + "regression_summary_table", + "remove_single_binary_outcome_predictors", + "rmv_high_corr", + "rmv_low_var", + "trim_field_label", + "variance_influence_factor_backwards_elimination", +] + + +# -- IMPORTS -- + +# -- Standard libraries -- +import typing import warnings +# -- 3rd party libraries -- import numpy as np import pandas as pd import statsmodels.api as sm @@ -14,6 +66,8 @@ from statsmodels.genmod.bayes_mixed_glm import BinomialBayesMixedGLM from statsmodels.stats.outliers_influence import variance_inflation_factor +# -- Internal libraries -- + ############################################ ############################################ # General preprocessing @@ -21,32 +75,46 @@ ############################################ -def extend_dictionary(dictionary, new_variable_dict, data, sep="___"): - """Add new custom variables to the VERTEX dictionary. - - Args: - dictionary (pd.DataFrame): - VERTEX dictionary containing columns 'field_name', 'form_name', - 'field_type', 'field_label', 'parent', 'branching_logic'. - new_variable_dict (dict): - A dict with the same keys as the dictionary columns, the values for - each item can be a string or a list. - data (pd.DataFrame): - pandas dataframe containing the data for the project. The columns - of this dataframe must include the variables in - new_variable_dict['field_type']. - sep (str): separator for creating new one-hot-encoded variable names. - - Returns: - dictionary (pd.DataFrame): - VERTEX dictionary containing the original variables, plus the new - variables and any one-hot-encoded variables derived from this.""" +def extend_dictionary( + dictionary: pd.DataFrame, + new_variable_dict: dict[str, typing.Any], + data: pd.DataFrame, + sep: str = "___", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns the VERTEX dictionary with new custom variables added. + + Parameters + ---------- + dictionary : pd.DataFrame) + VERTEX dictionary containing columns ``"field_name"``, ``"form_name"``, + ``"field_type"``, ``"field_label"``, ``"parent"``, ``"branching_logic"``. + + new_variable_dict : dict + A dict with the same keys as the dictionary columns, the values for + each item can be a string or a list. + + data : pd.DataFrame + Pandas dataframe containing the data for the project. The columns of + this dataframe must include the variables in + ``new_variable_dict["field_type"]``. + + sep : str + Separator for creating new one-hot-encoded variable names. + + Returns + ------- + pd.DataFrame + VERTEX dictionary containing the original variables, plus the new + variables and any one-hot-encoded variables derived from this. + """ # noqa : E501 # Convert dict values to list if all are strings (otherwise a pandas error) if all(isinstance(v, str) for v in new_variable_dict.values()): new_variable_dict = {k: [v] for k, v in new_variable_dict.items()} + new_dictionary = pd.DataFrame.from_dict(new_variable_dict) new_dictionary["index"] = np.nan dictionary = dictionary.reset_index(drop=False) + for ind in new_dictionary.index: parent = new_dictionary.loc[ind, "parent"] if parent not in new_dictionary["field_name"].values: @@ -72,6 +140,7 @@ def extend_dictionary(dictionary, new_variable_dict, data, sep="___"): ) # new_ind = new_ind + 0.1 new_dictionary.loc[ind, "index"] = new_ind + categorical_ind = new_dictionary["field_type"].isin(["categorical"]) new_dictionary_list = [new_dictionary] ind_list = [ @@ -79,6 +148,7 @@ def extend_dictionary(dictionary, new_variable_dict, data, sep="___"): for ind in categorical_ind.loc[categorical_ind].index if new_dictionary.loc[ind, "field_name"] in data.columns ] + for ind in ind_list: variable = new_dictionary.loc[ind, "field_name"] options = data[variable].drop_duplicates().sort_values().dropna() @@ -103,19 +173,21 @@ def extend_dictionary(dictionary, new_variable_dict, data, sep="___"): len(options), ) new_dictionary_list += [add_options] + dictionary = pd.concat([dictionary] + new_dictionary_list, axis=0) dictionary = dictionary.sort_values(by="index").drop(columns="index") dictionary = dictionary.reset_index(drop=True) + return dictionary def get_variables_by_section_and_type( - df, - dictionary, - required_variables=None, - include_sections=["demog"], - include_types=["binary", "categorical", "numeric"], - exclude_suffix=[ + data: pd.DataFrame, + dictionary: pd.DataFrame, + required_variables: typing.Iterable[str] | None = None, + include_sections: typing.Iterable[str] = ["demog"], + include_types: typing.Iterable[str] = ["binary", "categorical", "numeric"], + exclude_suffixes: typing.Iterable[str] = [ "_units", "addi", "otherl2", @@ -124,12 +196,43 @@ def get_variables_by_section_and_type( "_unlisted", "otherl3", ], - include_subjid=False, -): - """ - Get all variables in the dataframe from specified sections and types, - plus any required variables. - """ + include_subjid: bool = False, +) -> list[str]: + """:py:class:`list` : Returns a list of all variables in the dataframe from specified sections and types, plus any required variables. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + dictionary : pd.DataFrame + Data dictionary. + + required_variables : typing.Iterable, default=None + Optional iterable of required variable names, defaults to ``None``. + + include_sections : typing.Iterable, default=["demog"] + Optional iterable of names of sections to include, defaults to + ``["demog"]``. + + include_types : typing.Iterable, default=["binary", "categorical", "numeric"] + Optional iterable of variable type names, defaults to + ``["binary", "categorical", "numeric"]``. + + exclude_suffixes : typing.Iterable, default=``["_units", "addi", "otherl2", "item", "_oth", "_unlisted", "otherl3"]`` + Optional iterable of suffixes to exclude, defaults to + ``["_units", "addi", "otherl2", "item", "_oth", "_unlisted", "otherl3"]``. + + include_subjid : bool, default=False + Optional boolean to indicate whether to include subject ID, defaults + to ``False``. + + Returns + ------- + list + A list of all variables in the dataframe from specified sections and + types, plus any required variables. + """ # noqa : E501 if "section" in dictionary.columns: # TODO: this should always be True in future include_ind = dictionary["section"].isin(include_sections) else: @@ -141,7 +244,7 @@ def get_variables_by_section_and_type( # lambda x: x.endswith(tuple('___' + x for x in exclude_suffix))) == 0) include_ind &= ( dictionary["field_name"].apply( - lambda x: x.endswith(tuple(x for x in exclude_suffix)) + lambda x: x.endswith(tuple(x for x in exclude_suffixes)) ) == 0 ) @@ -150,28 +253,63 @@ def get_variables_by_section_and_type( if include_subjid: include_ind |= dictionary["field_name"] == "subjid" include_variables = dictionary.loc[include_ind, "field_name"].tolist() - include_variables = [col for col in include_variables if col in df.columns] - return include_variables + return [col for col in include_variables if col in data.columns] -def convert_categorical_to_onehot( - df, dictionary, categorical_columns, sep="___", missing_val="nan", drop_first=False -): - """Convert categorical variables into onehot-encoded variables.""" - categorical_columns = [col for col in df.columns if col in categorical_columns] - df.loc[:, categorical_columns] = df[categorical_columns].fillna(missing_val) - df = pd.get_dummies(df, columns=categorical_columns, prefix_sep=sep) +def convert_categorical_to_onehot( + data: pd.DataFrame, + dictionary: pd.DataFrame, + categorical_columns: typing.Iterable[str], + sep: str = "___", + missing_val: str = "nan", + drop_first: bool = False, +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns the given dataframe with categorical variable columns converted to onehot-encoded variable columns. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + categorical_columns : typing.Iterable + An iterable of categorical column names. + + sep : str, default="___" + Field-value separator, defaults to ``"___"`` + + missing_val : str, default="nan" + Optional value with which to replace missing values, defaults to + ``"nan"``. + + drop_first : bool, default=False + Optional boolean to indicate how to drop categorical columns [?], + defaults to ``False``. + + Returns + ------- + pd.DataFrame + The original dataframe with the categorical -> one-hot-encoded variable + columns. + """ # noqa : E501 + categorical_columns = [col for col in data.columns if col in categorical_columns] + + data.loc[:, categorical_columns] = data[categorical_columns].fillna(missing_val) + data = pd.get_dummies(data, columns=categorical_columns, prefix_sep=sep) for categorical_column in categorical_columns: onehot_columns = [ - var for var in df.columns if var.split(sep)[0] == categorical_column + var for var in data.columns if var.split(sep)[0] == categorical_column ] - df[onehot_columns] = df[onehot_columns].astype(object) - if (categorical_column + sep + missing_val) in df.columns: - mask = df[categorical_column + sep + missing_val] == 1 - df.loc[mask, onehot_columns] = np.nan - df = df.drop(columns=[categorical_column + sep + missing_val]) + data[onehot_columns] = data[onehot_columns].astype(object) + + if (categorical_column + sep + missing_val) in data.columns: + mask = data[categorical_column + sep + missing_val] == 1 + data.loc[mask, onehot_columns] = np.nan + data = data.drop(columns=[categorical_column + sep + missing_val]) elif ( drop_first and isinstance(dictionary, pd.DataFrame) @@ -185,54 +323,122 @@ def convert_categorical_to_onehot( axis=1, ) if drop_column_ind.any(): - df = df.drop( + data = data.drop( columns=[dictionary.loc[drop_column_ind, "field_name"].values[0]] ) if isinstance(dictionary, pd.DataFrame) and "field_name" in dictionary.columns: - columns = [col for col in dictionary["field_name"].values if col in df.columns] + columns = [ + col for col in dictionary["field_name"].values if col in data.columns + ] columns += [ - col for col in df.columns if col not in dictionary["field_name"].values + col for col in data.columns if col not in dictionary["field_name"].values ] - df = df[columns] + data = data[columns] - return df + return data def convert_onehot_to_categorical( - df, dictionary, categorical_columns, sep="___", missing_val="nan" -): - """Convert onehot-encoded variables into categorical variables.""" - df = pd.concat([df, pd.DataFrame(columns=categorical_columns)], axis=1) + data: pd.DataFrame, + dictionary: pd.DataFrame, + categorical_columns: typing.Iterable[str], + sep: str = "___", + missing_val: str = "nan", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns the given dataframe with onehot-encoded variable columns to categorical variable columns. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + Data dictionary. + + categorical_columns : typing.Iterable + An iterable of categorical column names. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + missing_val : str, default="nan" + Optional value with which to replace missing values, defaults to + ``"nan"``. + + Returns + ------- + pd.DataFrame + The original dataframe with the one-hot-encoded -> categorical variable + columns. + """ # noqa : E501 + data = pd.concat([data, pd.DataFrame(columns=categorical_columns)], axis=1) + for categorical_column in categorical_columns: onehot_columns = list( - df.columns[df.columns.str.startswith(categorical_column + sep)] + data.columns[data.columns.str.startswith(categorical_column + sep)] ) # Preserve missingness - df.loc[:, categorical_column + sep + missing_val] = ( - df[onehot_columns].any(axis=1) == 0 - ) | (df[onehot_columns].isna().any(axis=1)) + data.loc[:, categorical_column + sep + missing_val] = ( + data[onehot_columns].any(axis=1) == 0 + ) | (data[onehot_columns].isna().any(axis=1)) + with pd.option_context("future.no_silent_downcasting", True): - df.loc[:, onehot_columns] = df[onehot_columns].fillna(False) + data.loc[:, onehot_columns] = data[onehot_columns].fillna(False) onehot_columns += [categorical_column + sep + missing_val] - df.loc[:, categorical_column] = pd.from_dummies(df[onehot_columns], sep=sep) - df = df.drop(columns=onehot_columns) + data.loc[:, categorical_column] = pd.from_dummies(data[onehot_columns], sep=sep) + data = data.drop(columns=onehot_columns) - columns = [col for col in dictionary["field_name"].values if col in df.columns] - columns += [col for col in df.columns if col not in dictionary["field_name"].values] - df = df[columns] - return df + columns = [col for col in dictionary["field_name"].values if col in data.columns] + columns += [ + col for col in data.columns if col not in dictionary["field_name"].values + ] + data = data[columns] + + return data def from_timeA_to_timeB( - data, - dictionary, - timeA_column, - timeB_column, - timediff_column, - timediff_label, - time_unit="days", -): + data: pd.DataFrame, + dictionary: pd.DataFrame, + timeA_column: str, + timeB_column: str, + timediff_column: str, + timediff_label: str, + time_unit: str = "days", +) -> tuple[pd.DataFrame]: + """:py:class:`tuple` : Returns the data and data dictionary updated with time difference calculation between two given data columns. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + timeA_column : str + The name of the first time column. + + timeB_column : str + The name of the second time column. + + timediff_column : str + The name of the column for storing the time difference of the two + given time columns. + + timediff_label : str + A label to attach to the time difference column. + + time_unit : str, default="days" + An optional indicator of which time unit to use for the time difference + calculation, defaults to ``"days"``. + + Returns + ------- + tuple + The data and data dictionary updated with time difference information. + """ # noqa : E501 if time_unit == "days": data[timediff_column] = (data[timeB_column] - data[timeA_column]).dt.days elif time_unit == "months": @@ -241,6 +447,7 @@ def from_timeA_to_timeB( ) * 12 + (data[timeB_column].dt.month - data[timeA_column].dt.month) elif time_unit == "months": data[timediff_column] = data[timeB_column].dt.year - data[timeA_column].dt.year + time_dict = { "field_name": timediff_column, "form_name": dictionary.loc[ @@ -253,6 +460,7 @@ def from_timeA_to_timeB( ].values[0], } dictionary = extend_dictionary(dictionary, time_dict, data) + return data, dictionary @@ -263,7 +471,37 @@ def from_timeA_to_timeB( ############################################ -def median_iqr_str(series, add_spaces=False, dp=1, mfw=4, min_n=3): +def get_median_interquartile_range( + series: pd.Series, + add_spaces: bool = False, + dp: int = 1, + mfw: int = 4, + min_n: int = 3, +) -> str: + """:py:class:`str` : Returns the median interquartile range (IQR) of a given series of values as a string. + + Parameters + ---------- + series : pd.Series + The input series for which to calculate the IQR. + + add_spaces : bool, default=False + Add spacing in the string. + + dp : int, default=1 + No description available. + + mfw : int, default=4 + No description available. + + min_n : int, default=3 + No description available. + + Returns + ------- + str + The IQR as a string. + """ # noqa : E501 if series.notna().sum() < min_n: output_str = "N/A" elif add_spaces: @@ -277,10 +515,90 @@ def median_iqr_str(series, add_spaces=False, dp=1, mfw=4, min_n=3): output_str += "%.*f" % (dp, series.quantile(0.25)) + "-" output_str += "%.*f" % (dp, series.quantile(0.75)) + ") | " output_str += str(int(series.notna().sum())) + return output_str -def mean_std_str(series, add_spaces=False, dp=1, mfw=4, min_n=3): +def median_iqr_str( + series: pd.Series, + add_spaces: bool = False, + dp: int = 1, + mfw: int = 4, + min_n: int = 3, +) -> str: + """:py:class:`str` : Returns the median interquartile range (IQR) of a given series of values as a formatted string. + + .. warning:: + + DEPRECATED. Please use :py:func:`~isaricanalytics.analytics.get_median_interquartile_range` instead. + + Parameters + ---------- + series : pd.Series + The input series for which to calculate the IQR. + + add_spaces : bool, default=False + Add spacing in the string. + + dp : int, default=1 + No description available. + + mfw : int, default=4 + No description available. + + min_n : int, default=3 + No description available. + + Returns + ------- + str + The IQR as a string. + """ # noqa : E501 + warnings.warn( + ( + "`analytics.median_iqr_str` is deprecated; " + "please use `analytics.get_median_interquartile_range` instead." + ), + DeprecationWarning, + stacklevel=2, + ) + + return get_median_interquartile_range( + series, add_spaces=add_spaces, dp=dp, mfw=mfw, min_n=min_n + ) + + +def get_mean_and_stdev( + series: pd.Series, + add_spaces: bool = False, + dp: int = 1, + mfw: int = 4, + min_n: int = 3, +) -> str: + """:py:class:`str` : Returns the mean and standard deviation of a series of values as a formatted string. + + Parameters + ---------- + series : pd.Series + The input series for which to calculate the mean and st. dev. + + add_spaces : bool, default=False + Add spacing in the string. + + dp : int, default=1 + No description available. + + mfw : int, default=4 + No description available. + + min_n : int, default=3 + No description available. + + Returns + ------- + str + The mean and st. dev. as a formatted string. + """ # noqa : E501 if series.notna().sum() < min_n: output_str = "N/A" elif add_spaces: @@ -292,10 +610,90 @@ def mean_std_str(series, add_spaces=False, dp=1, mfw=4, min_n=3): output_str = "%.*f" % (dp, series.mean()) + " (" output_str += "%.*f" % (dp, series.std()) + ") | " output_str += str(int(series.notna().sum())) + return output_str -def n_percent_str(series, add_spaces=False, dp=1, mfw=4, min_n=1): +def mean_std_str( + series: pd.Series, + add_spaces: bool = False, + dp: int = 1, + mfw: int = 4, + min_n: int = 3, +) -> str: + """:py:class:`str` : Returns the mean and standard deviation of a series of values as a formatted string. + + .. warning:: + + DEPRECATED. Please use :py:func:`~isaricanalytics.analytics.get_mean_and_stdev` instead. + + Parameters + ---------- + series : pd.Series + The input series for which to calculate the mean and st. dev. + + add_spaces : bool, default=False + Add spacing in the string. + + dp : int, default=1 + No description available. + + mfw : int, default=4 + No description available. + + min_n : int, default=3 + No description available. + + Returns + ------- + str + The mean and st. dev. as a formatted string. + """ # noqa : E501 + warnings.warn( + ( + "`analytics.mean_std_str` is deprecated; " + "please use `analytics.get_mean_and_stdev` instead." + ), + DeprecationWarning, + stacklevel=2, + ) + + return get_mean_and_stdev( + series, add_spaces=add_spaces, dp=dp, mfw=mfw, min_n=min_n + ) + + +def get_n_percent_value( + series: pd.Series, + add_spaces: bool = False, + dp: int = 1, + mfw: int = 4, + min_n: int = 1, +) -> str: + """:py:class:`str` : Returns the n-percent value of a series as a string. + + Parameters + ---------- + series : pd.Series + The input series. + + add_spaces : bool, default=False + Add spacing around the string. + + dp : int, default=1 + No description available. + + mfw : int, default=1 + No description available. + + min_n : int, default=1 + No description available. + + Returns + ------- + str + The n-percent value of the series as a string. + """ # noqa : E501 if series.notna().sum() < min_n: output_str = "N/A" elif add_spaces: @@ -311,10 +709,87 @@ def n_percent_str(series, add_spaces=False, dp=1, mfw=4, min_n=1): percent = "%.*f" % (dp, 100 * series.mean()) denom = str(int(series.notna().sum())) output_str = f"{count} ({percent}) | {denom}" + return output_str -def get_chi2_pvalue(x, y, x_cat=[True, False], y_cat=[True, False]): +def n_percent_str( + series: pd.Series, + add_spaces: bool = False, + dp: int = 1, + mfw: int = 4, + min_n: int = 1, +) -> str: + """:py:class:`str` : Returns the n-percent value of a series as a string. + + .. warning:: + + DEPRECATED. Please use :py:func:`~isaricanalytics.analytics.get_n_percent_value` instead. + + Parameters + ---------- + series : pd.Series + The input series. + + add_spaces : bool, default=False + Add spacing around the string. + + dp : int, default=1 + No description available. + + mfw : int, default=1 + No description available. + + min_n : int, default=1 + No description available. + + Returns + ------- + str + The n-percent value of the series as a string. + """ # noqa : E501 + warnings.warn( + ( + "`analytics.n_percent_str` is deprecated; " + "please use `analytics.get_n_percent_value` instead." + ), + DeprecationWarning, + stacklevel=2, + ) + + return get_n_percent_value( + series, add_spaces=add_spaces, dp=dp, mfw=mfw, min_n=min_n + ) + + +def get_chi2_pvalue( + x: pd.Series, + y: pd.Series, + x_cat: typing.Iterable[typing.Any] = [True, False], + y_cat: typing.Iterable[typing.Any] = [True, False], +) -> float | np.nan: + """:py:class:`float` : Returns the :math`p`-value for a Chi-squared test. + + Parameters + ---------- + x : pd.Series + The first series/factor. + + y : pd.Series + The second series/factor. + + x_cat : typing.Iterable + An iterable of categories by which to group the first series. + + y_cat : typing.Iterable + An interable of categories by which to group the second series. + + Returns + ------- + float or np.nan + The :math:`p`-value for the test, either a :py:class:`float` or + :py:class:`np.nan`. + """ # noqa : E501 try: print(x.name) contingency = pd.crosstab( @@ -326,10 +801,38 @@ def get_chi2_pvalue(x, y, x_cat=[True, False], y_cat=[True, False]): pvalue = chi2_contingency(contingency).pvalue except ValueError: pvalue = np.nan + return pvalue -def get_fisher_exact_pvalue(x, y, x_cat=[True, False], y_cat=[True, False]): +def get_fisher_exact_pvalue( + x: pd.Series, + y: pd.Series, + x_cat: typing.Iterable[typing.Any] = [True, False], + y_cat: typing.Iterable[typing.Any] = [True, False], +): + """:py:class:`float` : Returns the :math:`p`-value for a Fisher exact test. + + Parameters + ---------- + x : pd.Series + The first series/factor. + + y : pd.Series + The second series/factor. + + x_cat : typing.Iterable + An iterable of categories by which to group the first series. + + y_cat : typing.Iterable + An interable of categories by which to group the second series. + + Returns + ------- + float or np.nan + The :math:`p`-value for the test, either a :py:class:`float` or + :py:class:`np.nan`. + """ # noqa : E501 try: contingency = pd.crosstab( pd.Categorical(x.loc[x.notna()], categories=x_cat), @@ -344,33 +847,63 @@ def get_fisher_exact_pvalue(x, y, x_cat=[True, False], y_cat=[True, False]): pvalue = result.pvalue except ValueError: pvalue = np.nan + return pvalue -def format_pvalue(pvalue, dp=3, min_val=0.001, significance={"*": 0.05, "**": 0.01}): +def format_pvalue( + pvalue: float, + dp: int = 3, + min_val: float = 0.001, + significance: dict[str, float] = {"*": 0.05, "**": 0.01}, +) -> str: + """:py:class:`str` : Returns a formatted :math:`p`-value string. + + Parameters + ---------- + pvalue : float + The :math:`p`-value. + + dp : int, default=3 + Optional. No description available, defaults to :math:`3`. + + min_val : float, default=0.001 + Optional. No description available, defaults to :math:`0.001`. + + significance : dict, default={"*": 0.05, "**": 0.01}. + Dict of significance levels, defaults to ``{"*": 0.05, "**": 0.01}``. + + Returns + ------- + str + The formatted :math:`p`-value string. + """ # noqa : E501 if pvalue < min_val: pvalue_str = f"<{min_val}" elif np.isnan(pvalue): pvalue_str = "" else: pvalue_str = "%.*f" % (dp, pvalue) + for key in significance: level = significance[key] min_threshold = max([v for k, v in significance.items() if (k != key)] + [0]) + if min_threshold > level: min_threshold = 0 if (pvalue < level) & (pvalue > (min_threshold - 1e-8)): pvalue_str = pvalue_str + f" ({key})" + return pvalue_str def get_descriptive_data( - data, - dictionary, - by_column=None, - include_sections=["demog"], - include_types=["binary", "categorical", "numeric"], - exclude_suffix=[ + data: pd.DataFrame, + dictionary: pd.DataFrame, + by_column: str | None = None, + include_sections: typing.Iterable[str] = ["demog"], + include_types: typing.Iterable[str] = ["binary", "categorical", "numeric"], + exclude_suffix: typing.Iterable[str] = [ "_units", "addi", "otherl2", @@ -379,14 +912,55 @@ def get_descriptive_data( "_unlisted", "otherl3", ], - include_subjid=False, - exclude_negatives=True, - sep="___", -): - df = data.copy() + include_subjid: bool = False, + exclude_negatives: bool = True, + sep: str = "___", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns descriptive data. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + dictionary : pd.DataFrame + Data dictionary. + + by_column : str, default=None + Optional. No description available, defaults to ``None``. + + include_sections : typing.Iterable, default=["demog"] + Optional list of names of sections to include, defaults to + ``["demog"]``. + + include_types : typing.Iterable, default=["binary", "categorical", "numeric"] + Optional iterable of variable type names, defaults to + ``["binary", "categorical", "numeric"]``. + + exclude_suffix : typing.Iterable, default=["_units", "addi", "otherl2", "item", "_oth", "_unlisted", "otherl3"] + Optional iterable of suffixes to exclude, defaults to + ``["_units", "addi", "otherl2", "item", "_oth", "_unlisted", "otherl3"]``. + + include_subjid : bool, default=False + Optional boolean to indicate whether to include subject ID, defaults to + ``False``. + + exclude_negatives : bool, default=True + Optional boolean to indicate whether to drop negatives, defaults to + ``True``. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + pd.DataFrame + Returns the descriptive data. + """ # noqa : E501 + _data = data.copy() include_columns = get_variables_by_section_and_type( - df, + _data, dictionary, include_types=include_types, include_subjid=include_subjid, @@ -395,57 +969,88 @@ def get_descriptive_data( ) if (by_column is not None) & (by_column not in include_columns): include_columns = [by_column] + include_columns - df = df[include_columns].dropna(axis=1, how="all").copy() + _data = _data[include_columns].dropna(axis=1, how="all").copy() # Convert categorical variables to onehot-encoded binary columns categorical_ind = dictionary["field_type"] == "categorical" columns = dictionary.loc[categorical_ind, "field_name"].tolist() columns = [col for col in columns if col != by_column] - df = convert_categorical_to_onehot( - df, dictionary, categorical_columns=columns, sep=sep + _data = convert_categorical_to_onehot( + _data, dictionary, categorical_columns=columns, sep=sep ) - if (by_column is not None) & (by_column not in df.columns): - df = convert_onehot_to_categorical( - df, dictionary, categorical_columns=[by_column], sep=sep + if (by_column is not None) & (by_column not in _data.columns): + _data = convert_onehot_to_categorical( + _data, dictionary, categorical_columns=[by_column], sep=sep ) negative_values = ("no", "never smoked") negative_columns = [ - col for col in df.columns if col.split(sep)[-1].lower() in negative_values + col for col in _data.columns if col.split(sep)[-1].lower() in negative_values ] if exclude_negatives: - df.drop(columns=negative_columns, inplace=True) + _data.drop(columns=negative_columns, inplace=True) # Remove columns with only NaN values - df = df.dropna(axis=1, how="all") - df.fillna({by_column: "Unknown"}, inplace=True) - return df + _data = _data.dropna(axis=1, how="all") + _data.fillna({by_column: "Unknown"}, inplace=True) + + return _data def descriptive_table( - data, - dictionary, - by_column=None, - include_totals=True, - column_reorder=None, - include_raw_variable_name=False, - sep="___", -): - """ - Descriptive table for binary (including onehot-encoded categorical) and - numerical variables in data. The descriptive table will have seperate - columns for each category that exists for the variable 'by_column', if - this is provided. - """ - df = data.copy() + data: pd.DataFrame, + dictionary: pd.DataFrame, + by_column: str | None = None, + include_totals: bool = True, + column_reorder: typing.Iterable[str] | None = None, + include_raw_variable_name: bool = False, + sep: str = "___", +) -> tuple[pd.DataFrame, str]: + """:py:class:`py:class:tuple` : Returns the descriptive table and table key for binary and numerical variables in the data. + + The descriptive table will have separate columns for each category that + exists for the ``by_column`` variable, if this is provided. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + dictionary : pd.DataFrame + Data dictionary. + + by_column : str, default=None + Optional. No description available, defaults to ``None``. + + include_totals : bool, default=None + Optional. No description available, defaults to ``None``. + + column_reorder : typing.Iterable, default=None + Optional iterable of names of columns to reorder by, defaults to + ``None``. + + include_raw_variable_name : bool, default=False + Optional boolean indicating whether to include the raw variable name, + defaults to ``False``. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + tuple + Returns the descriptive table and table key for binary and numerical + variables in the data. + """ # noqa : E501 + _data = data.copy() numeric_ind = dictionary["field_type"] == "numeric" numeric_columns = dictionary.loc[numeric_ind, "field_name"].tolist() - numeric_columns = [col for col in numeric_columns if col in df.columns] + numeric_columns = [col for col in numeric_columns if col in _data.columns] binary_ind = dictionary["field_type"] == "binary" binary_columns = dictionary.loc[binary_ind, "field_name"].tolist() - binary_columns = [col for col in binary_columns if col in df.columns] + binary_columns = [col for col in binary_columns if col in _data.columns] # Add columns for section headers and categorical questions index = numeric_columns + binary_columns @@ -454,76 +1059,113 @@ def descriptive_table( index = table_dictionary["field_name"].tolist() table_columns = ["Variable", "All"] + if by_column is not None: - add_columns = list(df[by_column].unique()) + add_columns = list(_data[by_column].unique()) if column_reorder is not None: table_columns += [col for col in column_reorder if col in add_columns] table_columns += [col for col in add_columns if col not in column_reorder] else: table_columns += add_columns + table_columns += ["Raw variable name"] table = pd.DataFrame("", index=index, columns=table_columns) - table["Raw variable name"] = [var if var in df.columns else "" for var in index] + table["Raw variable name"] = [var if var in _data.columns else "" for var in index] table["Variable"] = format_descriptive_table_variables( table_dictionary, sep=sep ).tolist() - mfw = int(np.log10(df.shape[0])) + 1 # Min field width, for formatting - table.loc[numeric_columns, "All"] = df[numeric_columns].apply( + mfw = int(np.log10(_data.shape[0])) + 1 # Min field width, for formatting + table.loc[numeric_columns, "All"] = _data[numeric_columns].apply( median_iqr_str, mfw=mfw ) - table.loc[binary_columns, "All"] = df[binary_columns].apply(n_percent_str, mfw=mfw) + table.loc[binary_columns, "All"] = _data[binary_columns].apply( + n_percent_str, mfw=mfw + ) totals = pd.DataFrame(columns=table_columns, index=["totals"]) totals["Variable"] = "Totals" - totals["All"] = df.shape[0] + totals["All"] = _data.shape[0] if by_column is not None: - choices_values = df[by_column].unique() + choices_values = _data[by_column].unique() for value in choices_values: - ind = df[by_column] == value + ind = _data[by_column] == value mfw = int(np.log10(ind.sum())) + 1 # Min field width, for format - table.loc[numeric_columns, value] = df.loc[ind, numeric_columns].apply( + table.loc[numeric_columns, value] = _data.loc[ind, numeric_columns].apply( median_iqr_str, mfw=mfw ) - table.loc[binary_columns, value] = df.loc[ind, binary_columns].apply( + table.loc[binary_columns, value] = _data.loc[ind, binary_columns].apply( n_percent_str, mfw=mfw ) totals[value] = ind.sum() table = table.reset_index(drop=True) + if include_totals: table = pd.concat([totals, table], axis=0).reset_index(drop=True) + table_key = "KEY
(*) Count (%) | N
(+) Median (IQR) | N" + if include_raw_variable_name is False: table.drop(columns=["Raw variable name"], inplace=True) + return table, table_key def descriptive_comparison_table( - data, - dictionary, - by_column=None, - include_totals=True, - column_reorder=None, - sep="___", - pvalue_significance={"*": 0.05, "**": 0.01}, -): - """ - Descriptive table for binary (including onehot-encoded categorical) and - numerical variables in data. The descriptive table will have seperate - columns for each category that exists for the variable 'by_column', if - this is provided. - """ - df = data.copy() + data: pd.DataFrame, + dictionary: pd.DataFrame, + by_column: str | None = None, + include_totals: bool = True, + column_reorder: typing.Iterable[str] | None = None, + sep: str = "___", + pvalue_significance: dict[str, float] = {"*": 0.05, "**": 0.01}, +) -> tuple[pd.DataFrame, str]: + """:py:class:`tuple` : Returns the descriptive comparison table and table key for binary (including onehot-encoded categorical) and numerical variables in data. + + The descriptive table will have separate columns for each category that + exists for the ``by_column`` variable, if this is provided. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + dictionary : pd.DataFrame + Data dictionary. + + by_column : str, default=None + Optional. No description available, defaults to ``None``. + + include_totals : bool, default=None + Optional. No description available, defaults to ``None``. + + column_reorder : typing.Iterable, default=None + Optional iterable of names of columns to reorder by, defaults to + ``None``. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + pvalue_significance : dict, default={"*": 0.05, "**": 0.01} + A dict of significance levels, defaults to ``{"*": 0.05, "**": 0.01}``. + + Returns + ------- + tuple + Returns the descriptive comparison table and table key for binary and + numerical variables in the data. + """ # noqa : E501 + _data = data.copy() numeric_ind = dictionary["field_type"] == "numeric" numeric_columns = dictionary.loc[numeric_ind, "field_name"].tolist() - numeric_columns = [col for col in numeric_columns if col in df.columns] + numeric_columns = [col for col in numeric_columns if col in _data.columns] binary_ind = dictionary["field_type"] == "binary" binary_columns = dictionary.loc[binary_ind, "field_name"].tolist() - binary_columns = [col for col in binary_columns if col in df.columns] + binary_columns = [col for col in binary_columns if col in _data.columns] # Add columns for section headers and categorical questions index = numeric_columns + binary_columns @@ -533,7 +1175,7 @@ def descriptive_comparison_table( table_columns = ["Variable", "All"] if by_column is not None: - add_columns = list(df[by_column].unique()) + add_columns = list(_data[by_column].unique()) if column_reorder is not None: table_columns += [col for col in column_reorder if col in add_columns] table_columns += [col for col in add_columns if col not in column_reorder] @@ -546,35 +1188,37 @@ def descriptive_comparison_table( table_dictionary, sep=sep, binary_symbol="†" ).tolist() - mfw = int(np.log10(df.shape[0])) + 1 # Min field width, for formatting - table.loc[numeric_columns, "All"] = df[numeric_columns].apply( + mfw = int(np.log10(_data.shape[0])) + 1 # Min field width, for formatting + table.loc[numeric_columns, "All"] = _data[numeric_columns].apply( median_iqr_str, mfw=mfw ) - table.loc[binary_columns, "All"] = df[binary_columns].apply(n_percent_str, mfw=mfw) + table.loc[binary_columns, "All"] = _data[binary_columns].apply( + n_percent_str, mfw=mfw + ) totals = pd.DataFrame(columns=table_columns, index=["totals"]) totals["Variable"] = "Totals" - totals["All"] = df.shape[0] + totals["All"] = _data.shape[0] if by_column is not None: - by_column_values = df[by_column].unique() + by_column_values = _data[by_column].unique() for value in by_column_values: - ind = df[by_column] == value + ind = _data[by_column] == value mfw = int(np.log10(ind.sum())) + 1 # Min field width, for format - table.loc[numeric_columns, value] = df.loc[ind, numeric_columns].apply( + table.loc[numeric_columns, value] = _data.loc[ind, numeric_columns].apply( median_iqr_str, mfw=mfw ) - table.loc[binary_columns, value] = df.loc[ind, binary_columns].apply( + table.loc[binary_columns, value] = _data.loc[ind, binary_columns].apply( n_percent_str, mfw=mfw ) totals[value] = ind.sum() if len(by_column_values) == 2: - y = df[by_column] == by_column_values[0] + y = _data[by_column] == by_column_values[0] pvalues = pd.Series(index=table.index) - pvalues.loc[numeric_columns] = df[numeric_columns].apply( + pvalues.loc[numeric_columns] = _data[numeric_columns].apply( lambda x: mannwhitneyu(x, y, nan_policy="omit").pvalue, axis=0 ) - pvalues.loc[binary_columns] = df[binary_columns].apply( + pvalues.loc[binary_columns] = _data[binary_columns].apply( lambda x: get_fisher_exact_pvalue(x, y), axis=0 ) table["p-value"] = pvalues.apply( @@ -593,6 +1237,7 @@ def descriptive_comparison_table( if (pvalues < v).any() ] ) + return table, table_key @@ -603,20 +1248,64 @@ def descriptive_comparison_table( ############################################ -def trim_field_label(x, max_len=40): +def trim_field_label(x: str, max_len: int = 40) -> str: + """:py:class:`str` : Trims field label using an optional max. length parameter that defaults to 40 characters. + + Parameters + ---------- + x : str + The input field label. + + max_len : int, default=40 + An optional maximum length parameter to use for trimming, defaults to + :math:`40`. + + Returns + ------- + str + The trimmed field label. + """ # noqa : E501 if len(x) > max_len: x = " ".join(x[:max_len].split(" ")[:-1]) + " ..." + return x def format_descriptive_table_variables( - dictionary, - max_len=100, - add_key=True, - sep="___", - binary_symbol="*", - numeric_symbol="+", -): + dictionary: pd.DataFrame, + max_len: int = 100, + add_key: bool = True, + sep: str = "___", + binary_symbol: str = "*", + numeric_symbol: str = "+", +) -> str: + """:py:class:`str` : Returns a formatted string of the descriptive table variable field names. + + Parameters + ---------- + dictionary : pd.DataFrame + The data dictionary. + + max_len : int, default=100 + Optional maximum length of field names, defaults to :math:`100`. + + add_key : bool, default=True + Optional. No description available, defaults to ``True``. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + binary_symbol : str, default="*" + Optional. No description available, defaults to ``"*"``. + + numeric_symbol : str, default="*" + Optional. No description available, defaults to ``"+"``. + + Returns + ------- + str + A formatted string of the descriptive table variable field names. + """ # noqa : E501 name = dictionary["field_name"].apply(lambda x: " ↳ " if sep in x else "") name += dictionary["field_type"].map({"section": ""}).fillna("") name += ( @@ -626,6 +1315,7 @@ def format_descriptive_table_variables( ) name += dictionary["field_type"].map({"section": ""}).fillna("") name += dictionary["field_name"].apply(lambda x: "" if sep in x else "") + if add_key is True: field_type = ( dictionary["field_type"] @@ -639,10 +1329,32 @@ def format_descriptive_table_variables( .fillna("") ) name += field_type * (dictionary["field_name"].str.contains(sep) == 0) + return name -def format_variables(dictionary, max_len=40, sep="___"): +def format_variables( + dictionary: pd.DataFrame, max_len: int = 40, sep: str = "___" +) -> str: + """:py:class:`str` : Returns a formatted string of the descriptive table variable field names. + + Parameters + ---------- + dictionary : pd.DataFrame + The data dictionary. + + max_len : int, default=40 + Optional maximum length of field names, defaults to :math:`40`. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + str + A formatted string of the descriptive table variable field names. + """ # noqa : E501 + def get_parent_label(x): if pd.isna(x) or not isinstance(x, str): return "" @@ -674,8 +1386,34 @@ def get_parent_label(x): ############################################ -def get_counts(df, dictionary, max_n_variables=10, sep="___"): - counts = df.apply(lambda x: x.sum()).T.reset_index() +def get_counts( + data: pd.DataFrame, + dictionary: pd.DataFrame, + max_n_variables: int = 10, + sep: str = "___", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns a dataframe of variable column counts. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + max_n_variables : int, default=10 + Optional number of variables for which to take counts, defaults to + :math:`10`. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + The variable column counts dataframe. + """ # noqa : E501 + counts = data.apply(lambda x: x.sum()).T.reset_index() counts.columns = ["variable", "count"] counts = counts.sort_values(by=["count"], ascending=False).reset_index(drop=True) @@ -688,29 +1426,52 @@ def get_counts(df, dictionary, max_n_variables=10, sep="___"): short_format_dict = dict(zip(dictionary["field_name"], short_format)) counts["label"] = counts["variable"].map(format_dict) counts["short_label"] = counts["variable"].map(short_format_dict) + return counts def get_proportions( - df, - dictionary, - max_n_variables=10, - ignore_branching_logic=False, - branching_logic="", - sep="___", -): + data: pd.DataFrame, + dictionary: pd.DataFrame, + max_n_variables: int = 10, + ignore_branching_logic: bool = False, + branching_logic: str = "", + sep: str = "___", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns a dataframe of proportional counts for variable columns. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + max_n_variables : int, default=10 + Optional number of variables for which to take counts, defaults to + :math:`10`. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + pd.DataFrame + A dataframe of proportional counts for variable columns. + """ # noqa : E501 if ignore_branching_logic: - columns = [col for col in df.columns] + columns = [col for col in data.columns] else: dictionary_subset = dictionary.loc[ (dictionary["branching_logic"] == branching_logic) ] columns = [ - col for col in df.columns if col in dictionary_subset["field_name"].values + col for col in data.columns if col in dictionary_subset["field_name"].values ] if len(columns) == 0: branching_logic = dictionary.loc[ - dictionary["field_name"].isin(df.columns), "branching_logic" + dictionary["field_name"].isin(data.columns), "branching_logic" ] branching_logic = branching_logic.values[0] dictionary_subset = dictionary.loc[ @@ -718,17 +1479,19 @@ def get_proportions( ] columns = [ col - for col in df.columns + for col in data.columns if col in dictionary_subset["field_name"].values ] + proportions = ( - df[columns].apply(lambda x: (x.sum() / x.count(), x.sum())).T.reset_index() + data[columns].apply(lambda x: (x.sum() / x.count(), x.sum())).T.reset_index() ) proportions.columns = ["variable", "proportion", "count"] proportions = proportions.sort_values(by=["count"], ascending=False).reset_index( drop=True ) + if proportions.shape[0] > max_n_variables: proportions = proportions.head(max_n_variables) @@ -743,17 +1506,42 @@ def get_proportions( short_format_dict = dict(zip(dictionary["field_name"], short_format)) proportions["label"] = proportions["variable"].map(format_dict) proportions["short_label"] = proportions["variable"].map(short_format_dict) + return proportions def get_upset_counts_intersections( - df, - dictionary, - proportions=None, # Deprecated - variables=None, - n_variables=5, - sep="___", -): + data: pd.DataFrame, + dictionary: pd.DataFrame, + variables: list[str] | None = None, + n_variables: int = 5, + sep: str = "___", +) -> tuple[pd.DataFrame]: + """:py:class:`pd.DataFrame` : Returns a dataframe of upset counts intersections. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + variables : list, default=None + Optional list of names of variable columns for which to take counts, + defaults to ``None``. + + n_variables : int, default=5 + Optional limit for the number of variable columns, defaults to :math:`5`. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + pd.DataFrame + A dataframe of upset counts intersections. + """ # noqa : E501 # Convert variables and column names into their formatted names long_format = format_variables(dictionary, max_len=1000, sep=sep) short_format = format_variables(dictionary, max_len=40, sep=sep) @@ -761,29 +1549,30 @@ def get_upset_counts_intersections( short_format_dict = dict(zip(dictionary["field_name"], short_format)) if variables is None: - variables = df.columns.tolist() + variables = data.columns.tolist() binary_columns = dictionary.loc[ (dictionary["field_type"] == "binary"), "field_name" ].tolist() variables = [col for col in variables if col in binary_columns] - variables = [var for var in variables if df[var].sum() > 0] - df = df[variables].astype(float).fillna(0) + variables = [var for var in variables if data[var].sum() > 0] + data = data[variables].astype(float).fillna(0) - counts = df.sum().astype(int).reset_index().rename(columns={0: "count"}) + counts = data.sum().astype(int).reset_index().rename(columns={0: "count"}) counts = counts.sort_values(by="count", ascending=False).reset_index(drop=True) counts["short_label"] = counts["index"].map(short_format_dict) counts["label"] = counts["index"].map(format_dict) variable_order_dict = dict(zip(counts["index"], counts.index)) variables = counts["index"].tolist() + if n_variables is not None: variables = variables[:n_variables] - df = df[variables] + data = data[variables] counts = counts.loc[counts["index"].isin(variables)] - intersections = df.loc[df.any(axis=1)].value_counts().reset_index() + intersections = data.loc[data.any(axis=1)].value_counts().reset_index() intersections["index"] = intersections.drop(columns="count").apply( lambda x: tuple(col for col in x.index if x[col] == 1), axis=1 ) @@ -806,20 +1595,50 @@ def get_upset_counts_intersections( ) keep_columns = ["index", "label", "count"] intersections = intersections[keep_columns].reset_index(drop=True) + return counts, intersections -def get_pyramid_data(df, column_dict, left_side="Female", right_side="Male"): +def get_pyramid_data( + data: pd.DataFrame, + column_dict: dict[str, str], + left_side: str = "Female", + right_side: str = "Male", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns dual stack pyramid data. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + column_dict : dict + Dict of pyramid keys and data column names. + + left_side : str, default="Female" + Optional label for the left side of the pyramid, defaults to + ``"Female"``. + + right_side : str, default="Male" + Optional label for the right side of the pyramid, defaults to + ``"Male"``. + + Returns + ------- + pd.DataFrame + Dual stack pyramid data. + """ keys = ["side", "y_axis", "stack_group"] # assert all(key in tuple(column_dict.keys()) for key in keys), 'Error' columns = [column_dict[key] for key in keys] - df_pyramid = df[["subjid"] + columns].copy() + df_pyramid = data[["subjid"] + columns].copy() df_pyramid = df_pyramid.groupby(columns, observed=True).count().reset_index() df_pyramid.rename(columns={"subjid": "value"}, inplace=True) df_pyramid.rename(columns={v: k for k, v in column_dict.items()}, inplace=True) df_pyramid = df_pyramid.loc[df_pyramid["side"].isin([left_side, right_side])] df_pyramid.loc[:, "left_side"] = df_pyramid["side"] == left_side df_pyramid = df_pyramid.sort_values(by="y_axis").reset_index(drop=True) + return df_pyramid @@ -831,13 +1650,21 @@ def get_pyramid_data(df, column_dict, left_side="Female", right_side="Male"): def get_modelling_data( - data, - dictionary, - outcome_columns, - include_sections=["demog", "comor", "adsym", "vacci", "vital", "sympt", "labs"], - required_variables=None, - include_types=["binary", "categorical", "numeric"], - exclude_suffix=[ + data: pd.DataFrame, + dictionary: pd.DataFrame, + outcome_columns: str | typing.Iterable[str], + include_sections: typing.Iterable[str] = [ + "demog", + "comor", + "adsym", + "vacci", + "vital", + "sympt", + "labs", + ], + required_variables: typing.Iterable[str] | None = None, + include_types: typing.Iterable[str] = ["binary", "categorical", "numeric"], + exclude_suffix: typing.Iterable[str] = [ "_units", "addi", "otherl2", @@ -846,19 +1673,69 @@ def get_modelling_data( "_unlisted", "otherl3", ], - include_subjid=False, - exclude_negatives=True, - fillna=True, - drop_first=False, - sep="___", -): - df = data.copy() + include_subjid: bool = False, + exclude_negatives: bool = True, + fillna: bool = True, + drop_first: bool = False, + sep: str = "___", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns modelling data. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + dictionary : pd.DataFrame + Data dictionary. + + outcome_columns : typing.Iterable + Outcome columns. + + include_sections : typing.Iterable, default=["demog", "comor", "adsym", "vacci", "vital", "sympt", "labs"] + Optional list of names of sections to include, defaults to + ``["demog", "comor", "adsym", "vacci", "vital", "sympt", "labs"]``. + + required_variables: typing.Iterable, default=None + Required variable column names, defaults to ``None``. + + include_types : typing.Iterable, default=["binary", "categorical", "numeric"] + Optional iterable of variable type names, defaults to + ``["binary", "categorical", "numeric"]``. + + exclude_suffix : typing.Iterable, default=["_units", "addi", "otherl2", "item", "_oth", "_unlisted", "otherl3"] + Optional iterable of suffixes to exclude, defaults to + ``["_units", "addi", "otherl2", "item", "_oth", "_unlisted", "otherl3"]``. + + include_subjid : bool, default=False + Optional boolean to indicate whether to include subject ID, defaults to + ``False``. + + exclude_negatives : bool, default=True + Optional boolean to indicate whether to drop negatives, defaults to + ``True``. + + fillna : bool, default=True + Optional boolean to fill nulls, defaults to ``True``. + + drop_first : bool, default=False + Optional boolean relating to dropping columns, defaults to ``False``. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + pd.DataFrame + Returns the modelling data. + """ # noqa : E501 + _data = data.copy() if isinstance(outcome_columns, str): outcome_columns = [outcome_columns] include_columns = get_variables_by_section_and_type( - df, + _data, dictionary, required_variables=required_variables, include_types=include_types, @@ -869,64 +1746,91 @@ def get_modelling_data( for outcome_column in outcome_columns: if outcome_column not in include_columns: include_columns = [outcome_column] + include_columns - df = df[include_columns].dropna(axis=1, how="all").copy() + _data = _data[include_columns].dropna(axis=1, how="all").copy() # Convert categorical variables to onehot-encoded binary columns categorical_ind = dictionary["field_type"] == "categorical" columns = dictionary.loc[categorical_ind, "field_name"].tolist() columns = [col for col in columns if col not in tuple(outcome_columns)] - df = convert_categorical_to_onehot( - df, dictionary, categorical_columns=columns, drop_first=drop_first, sep=sep + _data = convert_categorical_to_onehot( + _data, dictionary, categorical_columns=columns, drop_first=drop_first, sep=sep ) binary_ind = dictionary["field_type"] == "binary" columns = dictionary.loc[binary_ind, "field_name"].tolist() - columns = [col for col in columns if col in df.columns] + columns = [col for col in columns if col in _data.columns] if fillna is True: with pd.option_context("future.no_silent_downcasting", True): - df[columns] = df[columns].fillna(False) + _data[columns] = _data[columns].fillna(False) negative_values = ("no", "never smoked") negative_columns = [ - col for col in df.columns if col.split(sep)[-1].lower() in negative_values + col for col in _data.columns if col.split(sep)[-1].lower() in negative_values ] if exclude_negatives: - df.drop(columns=negative_columns, inplace=True) - return df + _data.drop(columns=negative_columns, inplace=True) + + return _data def variance_influence_factor_backwards_elimination( - data, dictionary, predictors_list, sep="___" -): - df = data.copy() + data: pd.DataFrame, + dictionary: pd.DataFrame, + predictors_list: typing.Iterable[str], + sep: str = "___", +) -> tuple[typing.Iterable[str], pd.DataFrame]: + """:py:class:`tuple` : Returns an iterable of retained columns and the VIF backwards elimination data. + + Parameters + ---------- + data : pd.DataFrame + Incoming data. + + dictionary : pd.DataFrame + Data dictionary. + + predictors_list : typing.Iterable + Iterable of predictor variable column names. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + tuple + An iterable of retained columns and the VIF backwards elimination data. + """ # noqa : E501 + _data = data.copy() numeric_ind = dictionary["field_type"] == "numeric" numeric_columns = dictionary.loc[numeric_ind, "field_name"].tolist() - numeric_columns = [col for col in numeric_columns if col in df.columns] + numeric_columns = [col for col in numeric_columns if col in _data.columns] numeric_columns = [col for col in numeric_columns if col in predictors_list] categorical_ind = dictionary["field_type"].isin(["binary"]) categorical_columns = dictionary.loc[categorical_ind, "field_name"].tolist() - categorical_columns = [col for col in categorical_columns if col in df.columns] + categorical_columns = [col for col in categorical_columns if col in _data.columns] categorical_columns = [col for col in categorical_columns if col in predictors_list] - df[numeric_columns] = (df[numeric_columns] - df[numeric_columns].mean()) / df[ - numeric_columns - ].std() + _data[numeric_columns] = ( + _data[numeric_columns] - _data[numeric_columns].mean() + ) / _data[numeric_columns].std() - df = 1.0 * pd.concat([df[numeric_columns], df[categorical_columns]], axis=1).astype( - float - ) + _data = 1.0 * pd.concat( + [_data[numeric_columns], _data[categorical_columns]], axis=1 + ).astype(float) - keep_columns = df.columns + keep_columns = _data.columns iterative_vif = pd.DataFrame(keep_columns, columns=["variable"]) + with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=RuntimeWarning) iterative_vif["vif_iter_1"] = [ - variance_inflation_factor(df[keep_columns].values, ii) + variance_inflation_factor(_data[keep_columns].values, ii) for ii in range(len(keep_columns)) ] n = 1 + while (iterative_vif["vif_iter_" + str(n)] > 10).any(): remove_column = iterative_vif.loc[ iterative_vif["vif_iter_" + str(n)].idxmax(), "variable" @@ -940,43 +1844,59 @@ def variance_influence_factor_backwards_elimination( with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=RuntimeWarning) vif["vif_iter_" + str(n)] = [ - variance_inflation_factor(df[keep_columns].values, ii) + variance_inflation_factor(_data[keep_columns].values, ii) for ii in range(len(keep_columns)) ] iterative_vif = pd.merge(iterative_vif, vif, how="left", on="variable") + return keep_columns, iterative_vif def remove_single_binary_outcome_predictors( - data, dictionary, predictors_list, outcome_str -): - """ - Removes binary predictors that are associated with only one outcome (e.g. - if all patients with some_variable=1 have outcome=1) - - Parameters: - - data: Pandas DataFrame containing the data. - - outcome_str: Name of the response variable. - - predictors_list: List of predictor variable names. - - Returns: - - updated_predictors_list: List of predictor variable names excluding - any that can't be used in the logistic regression model. - """ - df = data.copy() + data: pd.DataFrame, + dictionary: pd.DataFrame, + predictors: typing.Iterable[str], + outcome: str, +) -> typing.Iterable[str]: + """:py:class:`typing.Iterable` : Returns a list of retained columns in the data after removing single binary outcome predictor columns. + + Removes binary predictors that are associated with only one outcome, e.g. + if all patients with ``some_variable=1`` have ``outcome=1``. + + Parameters + ---------- + data: pd.DataFrame + The incoming data. + + dictionary: pd.DataFrame + The data dictionary. + + predictors: typing.Iterable + Iterable of predictor variable column names. + + outcome : str + The outcome string. + + Returns + ------- + typing.Iterable: + List of predictor variable column names excluding any that can't be + used in the logistic regression model. + """ # noqa : E501 + _data = data.copy() numeric_ind = dictionary["field_type"] == "numeric" numeric_columns = dictionary.loc[numeric_ind, "field_name"].tolist() - numeric_columns = [col for col in numeric_columns if col in df.columns] - numeric_columns = [col for col in numeric_columns if col in predictors_list] + numeric_columns = [col for col in numeric_columns if col in _data.columns] + numeric_columns = [col for col in numeric_columns if col in predictors] categorical_ind = dictionary["field_type"].isin(["binary"]) categorical_columns = dictionary.loc[categorical_ind, "field_name"].tolist() categorical_columns = [col for col in categorical_columns if col in data.columns] - categorical_columns = [col for col in categorical_columns if col in predictors_list] + categorical_columns = [col for col in categorical_columns if col in predictors] result = ( - df.groupby(outcome_str)[categorical_columns] + _data.groupby(outcome)[categorical_columns] .apply( lambda x: x.isin([True]).any() & x.isin([False]).any(), include_groups=False ) @@ -984,17 +1904,46 @@ def remove_single_binary_outcome_predictors( ) keep_columns = result.loc[result.all(axis=1)].index.tolist() keep_columns = keep_columns + numeric_columns + return keep_columns def regression_summary_table( - table, - dictionary, - highlight_predictors=None, - pvalue_significance=None, - result_type="OddsRatio", - sep="___", -): + table: pd.DataFrame, + dictionary: pd.DataFrame, + highlight_predictors: dict[str, typing.Iterable[str]] | None = None, + pvalue_significance: float | None = None, + result_type: str = "OddsRatio", + sep: str = "___", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns a regression summary table. + + Parameters + ---------- + table : pd.DataFrame + The incoming table. + + dictionary : pd.DataFrame + The data dictionary. + + highlight_predictors : dict, default=None + Optional. No description available, defaults to ``None``. + + pvalue_significance : int, default=5 + Optional :math:`p`-value significance level, defaults to ``None``. + + result_type : str, default="OddsRatio" + Optional. No description avaiable, defaults to ``"OddsRatio"``. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + pd.DataFrame + Regression summary table. + """ # noqa : E501 + # Convert variables and column names into their formatted names variables = table["Variable"].tolist() new_variables = ( variables @@ -1085,58 +2034,79 @@ def regression_summary_table( } table["Variable"] = table["Variable"].map(mapping_dict) table["Variable"] = table["Variable"] + add_key + return table def execute_glmm_regression( - elr_dataframe_df, - elr_outcome_str, - elr_predictors_list, - elr_groups_str, - model_type="linear", - print_results=True, - labels=False, - reg_type="multi", -): - """ - Executes a mixed effects model for linear or logistic regression. - - Parameters: - - elr_dataframe_df: Pandas DataFrame containing the data. - - elr_outcome_str: Name of the response variable. - - elr_predictors_list: List of predictor variable names. - - elr_groups_str: Name of the variable that defines the groups (random effect). - - model_type: 'linear' for linear regression or 'logistic' for logistic regression. - - print_results: If True, prints the summary of the results. - - labels: (Optional) Dictionary to map variable names to readable labels. - - reg_type: 'uni' or 'multi', to rename the output columns. - - Returns: - - elr_summary_df: DataFrame with the model results. - """ - + elr_dataframe_df: pd.DataFrame, + elr_outcome: str, + elr_predictors: typing.Iterable[str], + elr_groups: str, + model_type: str = "linear", + print_results: bool = True, + labels: dict[str, str] | None = None, + reg_type: str = "multi", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Executes a mixed effects model for linear or logistic regression. + + Parameters + ---------- + elr_dataframe_df : pd.DataFrame + The incoming data. + + elr_outcome : str + Name of the response variable. + + elr_predictors : typing.Iterable + Iterable of predictor variable names. + + elr_groups : str + Name of the variable that defines the groups (random effect). + + model_type : str, default="linear" + Optional regression model type - use ``"linear"`` for linear regression + or ``"logistic"`` for logistic regression; defaults to ``"linear"``. + + print_results : bool, default=True + Optional indicator of whether to print the results summary, defaults to + ``True``. + + labels : dict, default=None + Optional map of variable names to readable labels, defaults to + ``None``. + + reg_type : str, default="multi" + Optional regression type - ``"uni"`` for univariate, ``"multi"`` for + multivariate. Defaults to ``"multi"``. + + Returns + ------- + pd.DataFrame + Model results. + """ # noqa : E501 # Builds the formula - elr_formula_str = elr_outcome_str + " ~ " + " + ".join(elr_predictors_list) + elr_formula_str = elr_outcome + " ~ " + " + ".join(elr_predictors) # Converts predictor categorical variables elr_categorical_vars_list = elr_dataframe_df.select_dtypes( include=["object", "category"] ) elr_categorical_vars_list = elr_categorical_vars_list.columns.intersection( - elr_predictors_list + elr_predictors ) for elr_var_str in elr_categorical_vars_list: elr_dataframe_df[elr_var_str] = elr_dataframe_df[elr_var_str].astype("category") # Converts the groups column to string to ensure that the values are hashable - elr_dataframe_df[elr_groups_str] = elr_dataframe_df[elr_groups_str].astype(str) + elr_dataframe_df[elr_groups] = elr_dataframe_df[elr_groups].astype(str) if model_type.lower() == "linear": # Mixed linear model using MixedLM (following your function) elr_model_obj = smf.mixedlm( formula=elr_formula_str, data=elr_dataframe_df, - groups=elr_dataframe_df[elr_groups_str], + groups=elr_dataframe_df[elr_groups], ) elr_result_obj = elr_model_obj.fit() @@ -1153,12 +2123,11 @@ def execute_glmm_regression( "p-value": pvalues.values, } ) - elif model_type.lower() == "logistic": # Mixed logistic model using BinomialBayesMixedGLM (Bayesian approach via VB) # Defines vc_formula for random effect (random intercept per group) - vc_formula = {elr_groups_str: "0 + C({})".format(elr_groups_str)} + vc_formula = {elr_groups: "0 + C({})".format(elr_groups)} elr_model_obj = BinomialBayesMixedGLM.from_formula( formula=elr_formula_str, vc_formulas=vc_formula, data=elr_dataframe_df @@ -1310,31 +2279,47 @@ def elr_parse_variable_name(var_name): def execute_glm_regression( - elr_dataframe_df, - elr_outcome_str, - elr_predictors_list, - model_type="linear", - print_results=True, - labels=False, - reg_type="Multi", -): - """ - Executes a GLM (Generalized Linear Model) for linear or logistic regression. - - Parameters: - - elr_dataframe_df: Pandas DataFrame containing the data. - - elr_outcome_str: Name of the response variable. - - elr_predictors_list: List of predictor variable names. - - model_type: 'linear' for linear regression (Gaussian) or 'logistic' for - logistic regression (Binomial). - - print_results: If True, prints the results table. - - labels: (Optional) Dictionary to map variable names to readable labels. - - reg_type: Type of regression ('uni' or 'multi') to rename the output columns. + elr_dataframe_df: pd.DataFrame, + elr_outcome: str, + elr_predictors: typing.Iterable, + model_type: str = "linear", + print_results: bool = True, + labels: dict[str, str] | None = None, + reg_type: str = "Multi", +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Executes a GLM (Generalized Linear Model) for linear or logistic regression. + + Parameters + ---------- + elr_dataframe_df : pd.DataFrame + The incoming data. + + elr_outcome : str + Name of the response variable. + + elr_predictors: typing.Iterable + Iterable of predictor variable names. + + model_type : str, default="linear" + Optional indicator regression model type - use ``"linear"`` for linear + regression (Gaussian) or ``"logistic"`` for logistic regression + (Binomial); defaults to ``"linear"``. + + print_results : bool, default=True + Optional indicator of whether to print the results table, defaults to + ``True``. + + labels : dict, default=None + Optional map of variable names to readable labels, defaults to + ``None``.`. + + reg_type : str, default="multi" + Optional regression type - ``"uni"`` for univariate, ``"multi"`` for + multivariate. Defaults to ``"multi"``. Returns: - summary_df: DataFrame with the model results. - """ - + """ # noqa : E501 # Defines the family according to model_type if model_type.lower() == "logistic": family = sm.families.Binomial() @@ -1344,12 +2329,12 @@ def execute_glm_regression( raise ValueError("model_type must be 'linear' or 'logistic'") # Builds the formula - formula = elr_outcome_str + " ~ " + " + ".join(elr_predictors_list) + formula = elr_outcome + " ~ " + " + ".join(elr_predictors) # Converts categorical variables to 'category' type categorical_vars = elr_dataframe_df.select_dtypes( include=["object", "category"] - ).columns.intersection(elr_predictors_list) + ).columns.intersection(elr_predictors) for var in categorical_vars: elr_dataframe_df[var] = elr_dataframe_df[var].astype("category") @@ -1478,50 +2463,63 @@ def parse_variable_name(var_name): return summary_df -def execute_cox_model(df, duration_col, event_col, predictors, labels=None): - """ - Performs a Cox Proportional Hazards model without weights and - returns a summary of the results. - - Parameters: - - df: Pandas DataFrame containing the data. - - duration_col: String with the name of the time variable. - - event_col: String with the name of the outcome variable (binary event). - - predictors: List of strings with the names of predictor variables. - - labels (Optional): - Dictionary mapping variable names to readable labels. - Default is None. +def execute_cox_model( + data: pd.DataFrame, + duration_col: str, + event_col: str, + predictors: typing.Iterable[str], + labels: dict[str, str] | None = None, +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Executes a Cox Proportional Hazards model without weights and returns a summary of the results. - Returns: - - summary_df: DataFrame with the results of the Cox model. - """ + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + duration_col : str + Name of the time variable. + + event_col : str + Name of the outcome variable (binary event). + + predictors : typing.Iterable + Names of predictor variables. + labels : dict, default=None + Dictionary mapping variable names to readable labels, default=``None``. + + Returns + ------- + pd.DataFrame + Results of the Cox model. + """ # noqa : E501 # Ensure categorical variables are treated appropriately - categorical_vars = df.select_dtypes( + categorical_vars = data.select_dtypes( include=["object", "category"] ).columns.intersection(predictors) for var in categorical_vars: - df[var] = df[var].astype("category") + data[var] = data[var].astype("category") # Convert categorical variables to dummies - df = pd.get_dummies(df, columns=categorical_vars, drop_first=True) + data = pd.get_dummies(data, columns=categorical_vars, drop_first=True) # Ensure numerical variables have the correct type - df[duration_col] = pd.to_numeric(df[duration_col], errors="coerce") - df[event_col] = pd.to_numeric(df[event_col], errors="coerce") + data[duration_col] = pd.to_numeric(data[duration_col], errors="coerce") + data[event_col] = pd.to_numeric(data[event_col], errors="coerce") # Update predictors to include one-hot encoded columns predictors = [ c - for c in df.columns + for c in data.columns if c in predictors or any(c.startswith(p + "_") for p in categorical_vars) ] # Remove rows with missing values in essential columns - df = df.dropna(subset=[duration_col, event_col] + predictors) + data = data.dropna(subset=[duration_col, event_col] + predictors) # Select relevant columns - df_cox = df[[duration_col, event_col] + predictors] + df_cox = data[[duration_col, event_col] + predictors] # Fit the Cox model cph = CoxPHFitter() @@ -1549,19 +2547,54 @@ def execute_cox_model(df, duration_col, event_col, predictors, labels=None): return summary_df -def execute_kaplan_meier(df, duration_col, event_col, group_col, alpha=0.05, n_times=5): +def execute_kaplan_meier( + data: pd.DataFrame, + duration_col: str, + event_col: str, + group_col: str, + alpha=0.05, + n_times=5, +) -> tuple[pd.DataFrame, pd.DataFrame, float]: + """:py:class:`tuple` : Executes the Kaplan-Meier model and returns the results. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + duration_col : str + Name of the time variable. + + event_col : str + Name of the outcome variable (binary event). + + group_col : str + Name of the grouping column. + + alpha : float, default=0.05 + Optional alpha, defaults to :math:`0.05`. + + n_times : int, default=5 + Optional. No description available, defaults to :math:`5`. + + Returns + ------- + pd.DataFrame + A tuple consisting of the model results, risk table and the + :math:`p`-value. + """ # noqa : E501 # Remove rows with missing values in relevant columns - df = df.dropna(subset=[duration_col, event_col, group_col]) + data = data.dropna(subset=[duration_col, event_col, group_col]) kmf = KaplanMeierFitter() - unique_groups = df[group_col].sort_values().unique() + unique_groups = data[group_col].sort_values().unique() df_km = pd.DataFrame(columns=["timeline"]) - max_time = (df[duration_col].max() // n_times) * (n_times + 1) + max_time = (data[duration_col].max() // n_times) * (n_times + 1) times = np.arange(0, max_time, n_times) # Compute survival curves and confidence intervals for each group for group in unique_groups: - group_data = df[df[group_col] == group] + group_data = data[data[group_col] == group] kmf.fit( group_data[duration_col], event_observed=group_data[event_col], @@ -1584,8 +2617,8 @@ def execute_kaplan_meier(df, duration_col, event_col, group_col, alpha=0.05, n_t # Perform log-rank test if len(unique_groups) == 2: - group1_data = df[df[group_col] == unique_groups[0]] - group2_data = df[df[group_col] == unique_groups[1]] + group1_data = data[data[group_col] == unique_groups[0]] + group2_data = data[data[group_col] == unique_groups[1]] result = logrank_test( group1_data[duration_col], group2_data[duration_col], @@ -1595,7 +2628,7 @@ def execute_kaplan_meier(df, duration_col, event_col, group_col, alpha=0.05, n_t p_value = result.p_value elif len(unique_groups) > 2: result = multivariate_logrank_test( - df[duration_col], df[group_col], df[event_col] + data[duration_col], data[group_col], data[event_col] ) p_value = result.p_value else: @@ -1604,7 +2637,8 @@ def execute_kaplan_meier(df, duration_col, event_col, group_col, alpha=0.05, n_t # Generate risk table: number of individuals at risk over time risk_counts = { group: [ - ((df[group_col] == group) & (df[duration_col] >= t)).sum() for t in times + ((data[group_col] == group) & (data[duration_col] >= t)).sum() + for t in times ] for group in unique_groups } @@ -1625,108 +2659,144 @@ def execute_kaplan_meier(df, duration_col, event_col, group_col, alpha=0.05, n_t def impute_miss_val( - df, - dictionary, - outcome_column="outco_binary_outcome", - missing_threshold=0.7, - verbose=False, -): - """ + data: pd.DataFrame, + dictionary: pd.DataFrame, + outcome_column: str = "outco_binary_outcome", + missing_threshold: float = 0.7, + verbose: bool = False, +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : The data with missing values imputed. + Imputes missing values or drops columns based on missing value proportion - and median + and median. - Returns: - - df: DataFrame with missing values imputed or columns dropped - """ + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + outcome_column : str, default="outco_binary_outcome" + Optional outcome column, default=``"outco_binary_outcome"``. + + missing_threshold : float, default=0.7 + A proportional imputation threshold for missing values, defaults to + :math:`0.7`. + + verbose, bool=False + Optional indicator of whether to print imputations summary, defaults + to ``False``. + + Returns + ------- + pd.DataFrame + Data with missing values imputed or columns dropped. + """ # noqa : E501 keep_columns = ["subjid", outcome_column] numeric_ind = dictionary["field_type"] == "numeric" numeric_columns = dictionary.loc[numeric_ind, "field_name"].tolist() - numeric_columns = [col for col in numeric_columns if col in df.columns] + numeric_columns = [col for col in numeric_columns if col in data.columns] binary_ind = dictionary["field_type"] == "binary" binary_columns = dictionary.loc[binary_ind, "field_name"].tolist() - binary_columns = [col for col in binary_columns if col in df.columns] + binary_columns = [col for col in binary_columns if col in data.columns] categorical_ind = dictionary["field_type"].isin(["binary"]) categorical_columns = dictionary.loc[categorical_ind, "field_name"].tolist() - categorical_columns = [col for col in categorical_columns if col in df.columns] + categorical_columns = [col for col in categorical_columns if col in data.columns] # Calculate the proportion of missing values in each column - missing_proportions = df.isnull().mean() + missing_proportions = data.isnull().mean() # Identify columns to drop columns_to_drop = missing_proportions[ (missing_proportions > missing_threshold) ].index.tolist() columns_to_drop = [col for col in columns_to_drop if col not in keep_columns] - df = df.drop(columns=columns_to_drop) + data = data.drop(columns=columns_to_drop) - impute_columns = [col for col in df.columns if col not in keep_columns] + impute_columns = [col for col in data.columns if col not in keep_columns] # Impute missing values in remaining columns for col in impute_columns: if col in numeric_columns: - df[col] = df[col].fillna(df[col].median()) + data[col] = data[col].fillna(data[col].median()) if col in (binary_columns + categorical_columns): - df[col] = df[col].fillna(df[col].mode().values[0]) + data[col] = data[col].fillna(data[col].mode().values[0]) if verbose: print("\nSummary after Imputation") - print("Size of remaining data:", df.shape) - return df + print("Size of remaining data:", data.shape) + return data -def rmv_low_var( - df, - dictionary, - mad_threshold=0.1, - freq_threshold=0.05, - outcome_column="outco_binary_outcome", - verbose=False, -): - """ - Removes numerical variables with Median Absolute Deviation (MAD) below a - threshold. - Excludes binary columns from MAD calculation. - Removes binary columns with very low frequencies - Returns: - - df: pandas DataFrame with low MAD columns removed - """ +def rmv_low_var( + data: pd.DataFrame, + dictionary: pd.DataFrame, + mad_threshold: float = 0.1, + freq_threshold: float = 0.05, + outcome_column: str = "outco_binary_outcome", + verbose: bool = False, +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Removes numerical variables from the data with Median Absolute Deviation (MAD) below a given threshold. + + Excludes binary columns from MAD calculation. Removes binary columns with + very low frequencies. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + mad_threshold : float, default=0.1 + Optional MAD threshold, defaults to :math:`0.1`. + + freq_threshold : float, default=0.5 + Optional frequency threshold, defaults to :math:`0.05`. + + outcome_column : str, default=``"outco_binary_outcome"`` + Optional outcome column, defaults to ``"outco_binary_outcome"``. + + verbose : bool, default=False + Optional indicator of whether to print MAD analysis summary. + + Returns + ------- + pd.DataFrame + The data with low MAD columns removed. + """ # noqa : E501 keep_columns = ["subjid", outcome_column] numeric_ind = dictionary["field_type"] == "numeric" numeric_columns = dictionary.loc[numeric_ind, "field_name"].tolist() - numeric_columns = [col for col in numeric_columns if col in df.columns] + numeric_columns = [col for col in numeric_columns if col in data.columns] binary_ind = dictionary["field_type"] == "binary" binary_columns = dictionary.loc[binary_ind, "field_name"].tolist() - binary_columns = [col for col in binary_columns if col in df.columns] + binary_columns = [col for col in binary_columns if col in data.columns] # Remove single-valued columns first - single_value_columns = df.columns[df.nunique() == 1] + single_value_columns = data.columns[data.nunique() == 1] single_value_columns = [ col for col in single_value_columns if col not in keep_columns ] - df = df.drop(columns=single_value_columns) - - # Select numeric columns - # numeric_columns = df.select_dtypes(include=[np.number]).columns - - # Select numeric columns and identify binary columns - # numeric_cols = df.select_dtypes(include=[np.number]).columns - # binary_cols = df.columns[df.nunique() == 2] - # non_binary_cols = numeric_cols.difference(binary_cols) + data = data.drop(columns=single_value_columns) # Calculate low frequency binary numeric column # Handle binary columns - convert to numeric first - binary_counts = df[binary_columns].mean(axis=0) + binary_counts = data[binary_columns].mean(axis=0) binary_counts = binary_counts.apply(lambda x: min((x, 1 - x))) exclude_binary_columns = [ col for col in binary_columns if (binary_counts[col] < freq_threshold) ] mad_series = ( - df[numeric_columns] + data[numeric_columns] .apply(lambda x: x / x.abs().max(), axis=0) .apply(lambda x: np.median(np.abs(x - np.median(x)))) ) @@ -1740,8 +2810,8 @@ def rmv_low_var( # 3. Non-binary numeric columns with MAD above threshold # Start with all CAT columns exclude_columns = exclude_binary_columns + exclude_numeric_columns - keep_columns = [col for col in df.columns if col not in exclude_columns] - df = df[keep_columns] + keep_columns = [col for col in data.columns if col not in exclude_columns] + data = data[keep_columns] if verbose: print("\nMAD Analysis Summary:") @@ -1752,33 +2822,53 @@ def rmv_low_var( {len(binary_columns) - len(exclude_binary_columns)}""") print(f"""Columns removed due to low MAD: \ {len(numeric_columns) - len(exclude_numeric_columns)}""") - return df + return data -def rmv_high_corr( - df, - dictionary, - outcome_column="outco_binary_outcome", - correlation_threshold=0.5, - verbose=False, -): - """ - Removes variables if there is high multicollinearity, arbitrarily selecting - one variable to remove if the correlation between two variables is above - a threshold. - Returns: - - df: pandas DataFrame with high correlation variables removed - """ +def rmv_high_corr( + data: pd.DataFrame, + dictionary: pd.DataFrame, + outcome_column: str = "outco_binary_outcome", + correlation_threshold: float = 0.5, + verbose: bool = False, +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Removes variables in the data with high multicollinearity. + + Arbitrarily selecting one variable to remove if the correlation between two + variables is above a threshold. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + outcome_column : str, default=``"outco_binary_outcome"`` + Optional outcome column, defaults to ``"outco_binary_outcome"``. + + correlation_threshold : float, default=0.5 + Optional correlation threshold, defaults to :math:`0.5`. + + verbose : bool, default=False + Optional indicator of whether to print correlation summary. + + Returns + ------- + pd.DataFrame + The data with high correlation variables removed. + """ # noqa : E501 keep_columns = ["subjid", outcome_column] numeric_ind = dictionary["field_type"] == "numeric" numeric_columns = dictionary.loc[numeric_ind, "field_name"].tolist() - numeric_columns = [col for col in numeric_columns if col in df.columns] + numeric_columns = [col for col in numeric_columns if col in data.columns] # Step 1: Select numeric columns only # numeric_cols = df.select_dtypes(include=[np.number]).columns - df_numeric = df[numeric_columns] # DataFrame with only numeric columns + df_numeric = data[numeric_columns] # DataFrame with only numeric columns # Step 2: Calculate the correlation matrix corr_matrix = df_numeric.corr().abs() @@ -1794,57 +2884,81 @@ def rmv_high_corr( # Step 4: Drop highly correlated columns (arbitrarily drop second column) exclude_columns = corr_pairs["level_1"].unique().tolist() exclude_columns = [col for col in exclude_columns if col not in keep_columns] - - # # Step 3: Identify highly correlated columns with a double loop - # to_drop = set() # Use a set to avoid duplicates - # num_cols = corr_matrix.shape[0] - # - # for i in range(num_cols): - # for j in range(i + 1, num_cols): # Only look at the upper triangle - # if corr_matrix.iloc[i, j] > correlation_threshold: - # # Identify the columns with high correlation - # # col1 = corr_matrix.columns[i] # ?? - # col2 = corr_matrix.columns[j] - # - # # Add one of the columns to `to_drop` - # to_drop.add(col2) # Arbitrarily drop the second column - # - # # Step 4: Drop highly correlated columns - # exclude_columns = [col for col in list(to_drop) if col not in keep_columns] - df = df.drop(columns=exclude_columns) + data = data.drop(columns=exclude_columns) if verbose: print("\nCORR Summary") print(f"Columns removed due to high correlation: \ {len(exclude_columns)}") - return df + + return data def lasso_var_sel_binary( - df, - outcome_column="mapped_outcome", - metric="balanced_accuracy", - threshold=1e-3, - gridsearch_params={ + data: pd.DataFrame, + outcome_column: str = "mapped_outcome", + metric: str = "balanced_accuracy", + threshold: float = 1e-3, + gridsearch_params: dict[str, typing.Iterable[float]] = { "l1_ratios": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], "Cs": [1e-3, 3.16e-3, 1e-2, 3.16e-2, 1e-1, 3.16e-1, 1, 3.16, 10], }, - random_state=42, - verbose=False, - sep="___", -): - """ - Prepare data and select features using binary logistic regression with - elastic net penalty. + random_state: int = 42, + verbose: bool = False, + sep: str = "___", +) -> tuple[typing.Any]: + """:py:class:`tuple` : Prepares data and selects features using binary logistic regression with elastic net penalty. + Specifically designed for binary outcomes only. - """ - if outcome_column not in df.columns: + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + outcome_column : str, default="mapped_outcome" + Optional outcome column, defaults to ``"mapped_outcome"``. + + metric : str, default="balanced_accuracy" + Optional metric, defaults to ``"balanced_accuracy"``. + + threshold : float, default=1e-3 + Optional threshold, defaults to :math:`0.001`. + + gridsearch_params : dict, default={ + "l1_ratios": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], + "Cs": [1e-3, 3.16e-3, 1e-2, 3.16e-2, 1e-1, 3.16e-1, 1, 3.16, 10] + } + Optional grid search params, defaults to: + :: + + { + "l1_ratios": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], + "Cs": [1e-3, 3.16e-3, 1e-2, 3.16e-2, 1e-1, 3.16e-1, 1, 3.16, 10] + } + + random_state : int, default=42 + Optional random state, defaults to :math:`42`. + + verbose : bool, default=False + Optional indicator of whether to print the analysis, defaults to + ``False``. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ------- + tuple + Results tuple. + """ # noqa : E501 + if outcome_column not in data.columns: error_str = f"Outcome column {outcome_column} not found in DataFrame" raise ValueError(error_str) # Separate predictors and outcome - y = df[outcome_column].copy() - X_ini = df.drop(columns=[outcome_column]) + y = data[outcome_column].copy() + X_ini = data.drop(columns=[outcome_column]) if verbose: print(f"\nInitial shape of X: {X_ini.shape}") @@ -2067,11 +3181,32 @@ def lasso_var_sel_binary( ) -def create_grouped_results(selected_features, feature_importance, sep="___"): - """ - Create a DataFrame with all categories listed under their main fields, - with main fields sorted by their maximum coefficient magnitude. - """ +def create_grouped_results( + selected_features: typing.Iterable[str], + feature_importance: dict[str, float], + sep: str = "___", +) -> tuple[pd.DataFrame, typing.Iterable[str], typing.Iterable[str]]: + """:py:class:`tuple` : Creates and returns grouped feature results. + + The main dataFrame lists categories under their main fields, with main + fields sorted by their maximum coefficient magnitude. + + Parameters + ---------- + selected_features : typing.Iterable + An iterable of selected feature names. + + feature_importance : dict + A dict of feature names and coefficient weights. + + sep : str, default="___" + Optional field-value separator, defaults to ``"___"``. + + Returns + ---------- + tuple + Feature results. + """ # noqa : E501 # Step 1: Identify one-hot encoded and regular features categorical_fields = set() regular_features = [] @@ -2146,11 +3281,27 @@ def create_grouped_results(selected_features, feature_importance, sep="___"): return pd.DataFrame(results), sorted_fields, categorical_fields -def get_parameter_ranking(logistic, n_top=10, threshold=1e-3): - """ - Create a ranking of parameter combinations using stored scores - and coefficient paths. - """ +def get_parameter_ranking( + logistic: typing.Any, n_top: int = 10, threshold: float = 1e-3 +) -> pd.DataFrame: + """:py:class:pd.DataFrame : Returns a dataframe of rankings of parameter combinations using stored scores and coefficient paths. + + Parameters + ---------- + logistic : typing.Any + The logistic model. + + n_top : int, default=10 + Optional number of top ranking features to select, defaults to :math:`10`. + + threshold : float, default=1e-3 + Optional ranking threshold, defaults to :math:`0.001`. + + Returns + ------- + pd.DataFrame + The dataframe of parameter rankings. + """ # noqa : E501 # Create empty list to store parameter information param_scores = [] @@ -2167,16 +3318,12 @@ def get_parameter_ranking(logistic, n_top=10, threshold=1e-3): for C_idx, C in enumerate(Cs): # Get mean score across folds for this parameter combination score = logistic.scores_[first_class][:, C_idx, l1_ratio_idx].mean() - # fold_ind = ( - # logistic.scores_[first_class][:, C_idx, l1_ratio_idx].argmax()) + # Get coefficients for this parameter combination coef0 = logistic.coefs_paths_[first_class][0, C_idx, l1_ratio_idx, :] coef1 = logistic.coefs_paths_[first_class][1, C_idx, l1_ratio_idx, :] coef2 = logistic.coefs_paths_[first_class][2, C_idx, l1_ratio_idx, :] - # # Average across folds # Why is this the mean? - # mean_coef = np.mean(coef_path, axis=0) - # Count non-zero coefficients n_features0 = np.sum(np.abs(coef0) > threshold) n_features1 = np.sum(np.abs(coef1) > threshold) diff --git a/isaricanalytics/redcap_data.py b/isaricanalytics/redcap_data.py index 36a4454..7d9fc78 100644 --- a/isaricanalytics/redcap_data.py +++ b/isaricanalytics/redcap_data.py @@ -1,22 +1,84 @@ +from __future__ import annotations + +__all__ = [ + "add_answer_dict", + "add_onehot_variables", + "combine_unlisted_variables", + "convert_dictionary_field_type", + "convert_onehot_to_binary", + "get_branching_logic_variables", + "get_data_dictionary", + "get_df_forms", + "get_df_map", + "get_events_and_forms_info", + "get_form_event", + "get_label", + "get_labels", + "get_missing_data_codes", + "get_records", + "get_redcap_data", + "get_section_prefix", + "get_value", + "get_values", + "harmonise_age", + "homogenise_variables", + "initial_data_processing", + "is_unlisted_item", + "is_yesno", + "is_yesno_question", + "list_categorical_onehot_columns", + "list_checkbox_onehot_columns", + "load_countries_table", + "load_units_conversion_table", + "map_variable", + "rename_checkbox_variables", + "replace_with_nan_for_missing_code_checkbox", + "resolve_checkbox_branching_logic", + "user_assigned_to_dag", +] + + +# -- IMPORTS -- + +# -- Standard libraries -- import io import time +import typing +import warnings from pathlib import Path +# -- 3rd party libraries -- import numpy as np import pandas as pd import requests +# -- Internal libraries -- from isaricanalytics.logging.logger import setup_logger logger = setup_logger(__name__) ############################################ -# Functions that call to the API +# API-calling functions ############################################ -def user_assigned_to_dag(redcap_url, redcap_api_key): +def user_assigned_to_dag(redcap_url: str, redcap_api_key: str) -> bool: + """:py:class:`bool` : Whether the user is assigned to a data access group (DAG). + + Parameters + ---------- + redcap_url : str + REDCap URL. + + redcap_api_key : str + REDCap API key. + + Returns + ------- + bool + Whether the user is assigned to a REDCap DAG. + """ conex = { "token": redcap_api_key, "content": "dag", @@ -24,15 +86,39 @@ def user_assigned_to_dag(redcap_url, redcap_api_key): "returnFormat": "json", } response = requests.post(redcap_url, data=conex) - output = response.status_code == 403 - return output + + return response.status_code == 403 def get_records( - redcap_url, redcap_api_key, data_access_groups=None, user_assigned_to_dag=False -): - """Fetch records from the REDCap API""" + redcap_url: str, + redcap_api_key: str, + data_access_groups: typing.Iterable[str] | None = None, + user_assigned_to_dag: bool = False, +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns a dataframe of records from the REDCap API. + + Parameters + ---------- + redcap_url : str + REDCap URL. + + redcap_api_key : str + REDCap API key. + + data_access_groups : typing.Iterable, default=None + An iterable of data access group names. + + user_assigned_to_dag : bool, default=False + Whether the user is assigned to a data access group (DAG). + + Returns + ------- + pd.DataFrame + Records from the REDCap API data. + """ started = time.perf_counter() + if (data_access_groups is None) or (user_assigned_to_dag is False): logger.info("REDCap records export: requesting all records") conex = { @@ -51,18 +137,19 @@ def get_records( } response = requests.post(redcap_url, data=conex) logger.debug("HTTP Status: " + str(response.status_code)) - df = pd.read_csv( + data = pd.read_csv( io.StringIO(response.text), dtype={"subjid": "str"}, keep_default_na=False ) if data_access_groups is not None: - ind = df["redcap_data_access_group"].isin(data_access_groups) - df = df.loc[ind].reset_index(drop=True) + ind = data["redcap_data_access_group"].isin(data_access_groups) + data = data.loc[ind].reset_index(drop=True) else: logger.info( "REDCap records export: requesting DAG-scoped records for " f"{len(data_access_groups)} DAG(s)" ) df_list = [] + for dag in data_access_groups: unique_group = dag.replace("-", "").replace(" ", "_").lower()[:18] conex = { @@ -75,8 +162,8 @@ def get_records( response = requests.post(redcap_url, data=conex) if response.text != "1": logger.warning( - f"Data access group ID: {dag}. Warning: Could not \ -switch DAG to unique group name: {unique_group}" + f"Data access group ID: {dag}. Warning: Could not" + f"switch DAG to unique group name: {unique_group}" ) continue conex = { @@ -114,19 +201,35 @@ def get_records( ) continue if len(df_list) > 0: - df = pd.concat(df_list, axis=0) + data = pd.concat(df_list, axis=0) else: - df = None + data = None + elapsed = time.perf_counter() - started - row_count = 0 if df is None else len(df) + row_count = 0 if data is None else len(data) logger.info( f"REDCap records export complete in {elapsed:.1f}s " f"(rows={row_count})" ) - return df + return data + + +def get_data_dictionary(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns a data dictionary from the REDCap API. + + Parameters + ---------- + redcap_url : str + REDCap URL. + + redcap_api_key : str + REDCap API key. -def get_data_dictionary(redcap_url, redcap_api_key): - """Fetch the data dictionary from the REDCap API""" + Returns + ------- + pd.DataFrame + Data dictionary from the REDCap API. + """ conex = { "token": redcap_api_key, "content": "metadata", @@ -135,13 +238,26 @@ def get_data_dictionary(redcap_url, redcap_api_key): } # Make the API request response = requests.post(redcap_url, data=conex) - df = pd.read_csv(io.StringIO(response.text), keep_default_na=False) - return df + return pd.read_csv(io.StringIO(response.text), keep_default_na=False) + + +def get_events_and_forms_info(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns a combined dataframe of events, forms and their mapppings from the REDCap API. + + Parameters + ---------- + redcap_url : str + REDCap URL. + + redcap_api_key : str + REDCap API key. -def get_form_event(redcap_url, redcap_api_key): - """Get events, forms and their mapppings from the REDCap API and merge - into a single dataframe.""" + Returns + ------- + pd.DataFrame + Events, forms and their mapppings from the REDCap API. + """ # noqa: E501 conex = { "token": redcap_api_key, "content": "event", @@ -163,6 +279,7 @@ def get_form_event(redcap_url, redcap_api_key): "format": "csv", "returnFormat": "json", } + # Make the API request response = requests.post(redcap_url, data=conex) if response.status_code == 200: @@ -180,6 +297,7 @@ def get_form_event(redcap_url, redcap_api_key): "format": "csv", "returnFormat": "json", } + # Make the API request response = requests.post(redcap_url, data=conex) if response.status_code == 200: @@ -199,50 +317,195 @@ def get_form_event(redcap_url, redcap_api_key): form_event = pd.merge( form_event, event, on=["unique_event_name", "arm_num"], how="left" ) + return form, form_event -def get_missing_data_codes(redcap_url, redcap_api_key): - """Get missing data codes from REDCAP API, using the project metadata""" +def get_form_event(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns a combined dataframe of events, forms and their mapppings from the REDCap API. + + .. warning:: + + DEPRECATED. + + Parameters + ---------- + redcap_url : str + REDCap URL. + + redcap_api_key : str + REDCap API key. + + Returns + ------- + pd.DataFrame + Events, forms and their mapppings from the REDCap API. + """ # noqa: E501 + warnings.warn( + ( + "`redcap_data.get_form_event` is deprecated; " + "use `redcap_data.get_events_and_forms_info` instead." + ), + DeprecationWarning, + stacklevel=2, + ) + + return get_events_and_forms_info(redcap_url, redcap_api_key) + + +def get_missing_data_codes(redcap_url: str, redcap_api_key: str) -> dict[str, str]: + """:py:class:`dict` : Returns missing data codes from the REDCAP API, using the project metadata. + + Parameters + ---------- + redcap_url : str + REDCap URL. + + redcap_api_key : str + REDCap API key. + + Returns + ------- + dict + A dict of missing data codes from the REDCap API, using the project + metadata. An empty dict is returned in the case there are no missing + data codes. + + """ # noqa: E501 conex = { "token": redcap_api_key, "content": "project", "format": "csv", "returnFormat": "json", } + response = requests.post(redcap_url, data=conex) - df = pd.read_csv(io.StringIO(response.text), keep_default_na=False) - if df["missing_data_codes"].isna().all(): - missing_data_codes = dict() + + data = pd.read_csv(io.StringIO(response.text), keep_default_na=False) + + if data["missing_data_codes"].isna().all(): + return dict() else: - missing_data_codes = df["missing_data_codes"].values[0] - missing_data_codes = dict( + missing_data_codes = data["missing_data_codes"].values[0] + return dict( zip( [x.split(",")[1].strip() for x in missing_data_codes.split("|")], [x.split(",")[0].strip() for x in missing_data_codes.split("|")], ) ) - return missing_data_codes -############################################ -# Functions for processing the data dictionary -############################################ +########################################################## +# Functions related to the data dictionary +########################################################## + + +def get_values(x: typing.Iterable[str]) -> list[str]: + """:py:class:`list` : Returns a list of values. + + Parameters + ---------- + x : typing.Iterable + An iterable of value tuples. + + Returns + ------- + list + A list of values. + """ + return [y.split(",")[0] for y in x] -def get_value(x): - values = [y.split(",")[0] for y in x] - return values +def get_value(x: typing.Iterable[str]) -> list[str]: + """:py:class:`list` : Returns a list of values. + .. warning:: -def get_label(x): - labels = [",".join(y.split(",")[1:]).strip() for y in x] - return labels + DEPRECATED. + Parameters + ---------- + x : typing.Iterable + An iterable of value tuples. + + Returns + ------- + list + A list of values. + """ + warnings.warn( + ( + "`redcap_data.get_value` is deprecated; " + "use `redcap_data.get_values` instead." + ), + DeprecationWarning, + stacklevel=2, + ) + + return get_values(x) + + +def get_labels(x: typing.Iterable[str]) -> list[str]: + """:py:class:`list` : Returns a list of labels. + + Parameters + ---------- + x : typing.Iterable + An iterable of label tuples. + + Returns + ------- + list + A list of labels. + """ + return [",".join(y.split(",")[1:]).strip() for y in x] + + +def get_label(x: typing.Iterable[str]) -> list[str]: + """:py:class:`list` : Returns a list of labels. + + .. warning:: + + DEPRECATED. -def add_answer_dict(dictionary): - """Add a lookup dict of labels/values to the dictionary from REDCap schema. - By default, ignore Yes/No/Unknown radio variables.""" + Parameters + ---------- + x : typing.Iterable + An iterable of label tuples. + + Returns + ------- + list + A list of labels. + """ + warnings.warn( + ( + "`redcap_data.get_label` is deprecated; " + "use `redcap_data.get_labels` instead." + ), + DeprecationWarning, + stacklevel=2, + ) + + return get_labels(x) + + +def add_answer_dict(dictionary: pd.DataFrame) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns the REDCap schema data dictionary with a lookup dict of labels and values. + + By default, ignores Yes/No/Unknown radio variables. + + Parameters + ---------- + dictionary : pd.DataFrame + REDCap schema data dictionary. + + Returns + ------- + pd.DataFrame + An updated REDCap schema data dictionary with a lookup dict of labels + and values. + """ # noqa: E501 new_dictionary = dictionary.copy() # Get categories from dictionary answers = new_dictionary["select_choices_or_calculations"].copy() @@ -262,34 +525,107 @@ def add_answer_dict(dictionary): answers = answers.apply(lambda x: dict(zip(get_label(x), get_value(x)))) answers.name = "answer_dict" new_dictionary = pd.concat([new_dictionary, answers], axis=1) + return new_dictionary -def list_categorical_onehot_columns(dictionary_row, data, sep="___"): +def list_categorical_onehot_columns( + dictionary_row: dict[str, typing.Any], data: pd.DataFrame, sep: str = "___" +) -> list[str]: + """:py:class:`list` Returns a list of categorical onehot-encoded columns in the given dataframe. + + Parameters + ---------- + dictionary_row : dict + A row of the data dictionary. + + data : pd.DataFrame + The incoming data. + + sep : str, default="___" + Separator of field/variable name and value in the list. + + Returns + ------- + list + A list of categorical onehot-encoded columns in the given dataframe. + """ # noqa: E501 variable = dictionary_row["field_name"] answers = dictionary_row["answer_dict"].keys() - output = [variable + sep + y for y in answers if y in data[variable].values] - return output + return [variable + sep + y for y in answers if y in data[variable].values] + + +def list_checkbox_onehot_columns( + dictionary_row: dict[str, typing.Any], data: pd.DataFrame, sep: str = "___" +) -> list[str]: + """:py:class:`list` Returns a list of checkbox onehot-encoded columns in the given dataframe. + + Parameters + ---------- + dictionary_row : dict + A row of the data dictionary. + + data : pd.DataFrame + The incoming data. -def list_checkbox_onehot_columns(dictionary_row, data, sep="___"): + sep : str, default="___" + Optional separator of field/variable name and value in the list. + + Returns + ------- + list + A list of checkbox onehot-encoded columns in the given dataframe. + """ # noqa: E501 variable = dictionary_row["field_name"] answers = dictionary_row["answer_dict"].keys() columns = [variable + sep + x for x in answers] - output = [col for col in columns if col in data.columns] - return output + return [col for col in columns if col in data.columns] + + +def get_section_prefix(x: str) -> str: + """:py:class:`str` : Returns the section prefix. + + Parameters + ---------- + x : str + Section name/value. + + Returns + ------- + str + The section prefix. + """ + return x.split("_data")[-1] if x.startswith("daily") else x.split("_")[0] -def get_section_prefix(x): - output = x.split("_data")[-1] if x.startswith("daily") else x.split("_")[0] - return output +def add_onehot_variables( + data: pd.DataFrame, dictionary: pd.DataFrame, sep: str = "___" +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Returns the data dictionary with rows for onehot-encoded categorical variables. -def add_onehot_variables(data, dictionary, sep="___"): - """Add new rows to the dictionary for onehot-encoded categorical variables, + Add new rows to the dictionary for onehot-encoded categorical variables, using only the answers that exist within the data, e.g. if checkbox columns exist (after removing columns with only 'Unchecked') or if radio column - answers are present for at least one subjid.""" + answers are present for at least one subjid. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The data dictionary. + + sep : str, default="___" + Optional separator of field/variable names and values. + + Returns + ------- + pd.DataFrame + The data dictionary with rows for onehot-encoded categorical variables. + """ # noqa: E501 new_dictionary = dictionary.copy() new_dictionary["parent"] = "" ind = new_dictionary["field_name"].str.contains("_") @@ -356,19 +692,76 @@ def add_onehot_variables(data, dictionary, sep="___"): sections.index -= 0.5 new_dictionary = pd.concat([new_dictionary, sections], axis=0) new_dictionary = new_dictionary.sort_index().reset_index(drop=True) + return new_dictionary -def is_yesno(x): - """Check if a Yes/No/Unknown question. Remove spaces in case of different - versions of the same string.""" - output = x.replace(" ", "") in ("1,Yes|0,No|99,Unknown", "1,Yes|0,No") - # output = output.isin(['1,Yes|0,No|99,Unknown', '1,Yes|0,No']) - return output +def is_yesno_question(x: str) -> str: + """:py:class:`str` : Returns a cleaned version of a Yes/No/Unknown question string. + Checks if the string is a Yes/No/Unknown question, and removes spaces in + case there are variations in the same string. -def convert_dictionary_field_type(dictionary): - """Get a dictionary of variable types, based on REDCAP structure""" + Parameters + ---------- + x : str + A question string. + + Returns + ------- + str + A cleaned version of the string if it is a Yes/No/Unknown question. + Otherwise the original is returned. + """ + return x.replace(" ", "") in ("1,Yes|0,No|99,Unknown", "1,Yes|0,No") + + +def is_yesno(x: str) -> str: + """:py:class:`str` : Returns a cleaned version of a Yes/No/Unknown question string. + + .. warning:: + + DEPRECATED. + + Checks if the string is a Yes/No/Unknown question, and removes spaces in + case there are variations in the same string. + + Parameters + ---------- + x : str + A question string. + + Returns + ------- + str + A cleaned version of the string if it is a Yes/No/Unknown question. + Otherwise the original is returned. + """ + warnings.warn( + ( + "`redcap_data.is_yesno` is deprecated; " + "use `redcap_data.is_yesno_question` instead." + ), + DeprecationWarning, + stacklevel=2, + ) + + return is_yesno_question(x) + + +def convert_dictionary_field_type(dictionary: pd.DataFrame) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Return a dictionary of variable types, based on REDCAP structure. + + Parameters + ---------- + dictionary : pd.DataFrame + The REDCap data dictionary. + + Returns + ------- + pd.DataFrame + a dictionary of variable types, based on REDCAP structure. + """ # noqa : E501 new_dictionary = dictionary.copy() val_column = "text_validation_type_or_show_slider_number" @@ -401,65 +794,116 @@ def convert_dictionary_field_type(dictionary): return new_dictionary -def replace_with_nan_for_missing_code_checkbox(df, missing_data_codes): - """Convert checkbox values to NaN when a missing code checkbox is 'Checked'""" +def replace_with_nan_for_missing_code_checkbox( + data: pd.DataFrame, missing_data_codes: dict[str, typing.Any] +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Return the input dataframe with missing code checkbox values converted to NaN. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + missing_data_codes : dict + A dict of missing code keys and values. + + Returns + ------- + pd.DataFrame + The input dataframe with missing code checkbox values converted to NaN. + """ # noqa : E501 missing_data_values = [x.lower() for x in missing_data_codes.values()] missing_columns = [ - col for col in df.columns if col.split("___")[-1] in missing_data_values + col for col in data.columns if col.split("___")[-1] in missing_data_values ] - nan_mask = (df[missing_columns] == "Checked").T.reset_index() + nan_mask = (data[missing_columns] == "Checked").T.reset_index() nan_mask["index"] = nan_mask["index"].apply(lambda x: x.split("___")[0]) nan_mask = nan_mask.groupby("index").any() - columns = [col for col in df.columns if col.split("___")[0] in nan_mask.index] + columns = [col for col in data.columns if col.split("___")[0] in nan_mask.index] nan_mask = nan_mask.loc[[col.split("___")[0] for col in columns]] nan_mask["column"] = columns nan_mask = nan_mask.set_index("column").T - df[nan_mask] = np.nan - return df + data[nan_mask] = np.nan + + return data ############################################ -# Functions for processing the data +# Data transformations ############################################ -def is_unlisted_item(x): - output = "".join([y for y in x if y.isdigit() is False]).endswith("unlisted_item") - return output +def is_unlisted_item(x: typing.Iterable[str]) -> str: + """:py:class:`str` : + + Parameters + --------- + x : typing.Iterable + An iterable of strings. + + Returns + ------- + str + - + """ + return "".join([y for y in x if y.isdigit() is False]).endswith("unlisted_item") + +def combine_unlisted_variables( + data: pd.DataFrame, dictionary: pd.DataFrame, sep: str = "___" +) -> tuple[pd.DataFrame]: + """:py:class:`tuple` : Combine variables in repetitions of a question. -def combine_unlisted_variables(df, dictionary, sep="___"): - """Combine variables that exist in repeated versions of the same question + Combine variables that exist in repeated versions of the same question (e.g. additional dropdown questions asked after Yes/No/Unknown questions - for established variables) + for established variables). + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The REDCap data dictionary. + + sep : str, default="___" + Optional value separator. + + Returns + ------- + tuple + The update data and data dictionary. """ unlisted_ind = dictionary["field_name"].str.endswith("unlisted") unlisted_columns = dictionary.loc[unlisted_ind, "field_name"] unlisted_item_ind = dictionary["field_name"].apply(is_unlisted_item) unlisted_item_columns = dictionary.loc[unlisted_item_ind, "field_name"] - unlisted_item_columns = [col for col in unlisted_item_columns if col in df.columns] + unlisted_item_columns = [ + col for col in unlisted_item_columns if col in data.columns + ] unlisted_columns_dict = { k: [v for v in unlisted_item_columns if k in v] for k in unlisted_columns } new_dictionary_list = [] + for ind in unlisted_columns.index: column = dictionary.loc[ind, "field_name"] - values = df[unlisted_columns_dict[column]].stack().unique() + values = data[unlisted_columns_dict[column]].stack().unique() values = [val for val in values if val not in (np.nan, "", "Other")] - new_df = pd.DataFrame( - index=df.index, columns=[column + "_item" + sep + x for x in values] + new_data = pd.DataFrame( + index=data.index, columns=[column + "_item" + sep + x for x in values] ) for value in values: # it's too slow... - yes_ind = (df[unlisted_columns_dict[column]] == value).any(axis=1) - new_df.loc[yes_ind, column + "_item" + sep + value] = True - column_loc = df.columns.get_loc(column) - df = pd.concat( - [df.iloc[:, :column_loc], new_df, df.iloc[:, column_loc:]], axis=1 + yes_ind = (data[unlisted_columns_dict[column]] == value).any(axis=1) + new_data.loc[yes_ind, column + "_item" + sep + value] = True + column_loc = data.columns.get_loc(column) + data = pd.concat( + [data.iloc[:, :column_loc], new_data, data.iloc[:, column_loc:]], axis=1 ) new_dictionary_index = ind + np.linspace(0.1, 0.9, len(values)) new_dictionary = pd.DataFrame( @@ -474,14 +918,33 @@ def combine_unlisted_variables(df, dictionary, sep="___"): new_dictionary["form_name"] = dictionary.loc[ind, "form_name"] new_dictionary["branching_logic"] = dictionary.loc[ind, "branching_logic"] new_dictionary_list.append(new_dictionary) + dictionary = pd.concat([dictionary] + new_dictionary_list, axis=0) dictionary = dictionary.sort_index().reset_index(drop=True) - return df, dictionary + return data, dictionary -def rename_checkbox_variables(df, dictionary): - """Rename checkbox variable columns. By default the suffix is their answer - option value. Convert this answer option value to the answer option name. + +def rename_checkbox_variables( + data: pd.DataFrame, dictionary: pd.DataFrame +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Rename checkbox variable columns. + + By default the suffix is their answer option value. Convert this answer + option value to the answer option name. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The REDCap data dictionary. + + Returns + ------- + pd.DataFrame + The updated data. """ checkbox_ind = dictionary["field_type"] == "checkbox" answer_dict = dictionary.loc[checkbox_ind, "answer_dict"] @@ -495,63 +958,146 @@ def rename_checkbox_variables(df, dictionary): # value codes, if they exist name_values = [x + "___" + y.lower() for x, y in zip(names, values)] name_labels = [x + "___" + y for x, y in zip(names, labels)] - df.rename(columns=dict(zip(name_values, name_labels)), inplace=True) - return df + data.rename(columns=dict(zip(name_values, name_labels)), inplace=True) + return data -def get_branching_logic_variables(branching_logic): - """Get all variables included in the branching logic - (including checkboxes variables)""" - var_names = [x.split("]")[0] for x in branching_logic.split("[")[1:]] - # Change any checkbox variable from bracket form to its one-hot column name - var_names = [x.replace("(", "___").replace(")", "") for x in var_names] - return var_names +def get_branching_logic_variables(branching_logic: str) -> list[str]: + """:py:class:`list` : Return all variables included in the branching logic (including checkboxes variables). -def resolve_checkbox_branching_logic(df, dictionary): - """By default, a cell is marked as 'Unchecked' in the absence of the + Parameters + ---------- + branching_logic : str + THe branching logic string. + + Returns + ------- + list + The list of all variables included in the branching logic. + """ # noqa : E501 + return [ + x.split("]")[0].replace("(", "___").replace(")", "") + for x in branching_logic.split("[")[1:] + ] + + +def resolve_checkbox_branching_logic( + data: pd.DataFrame, dictionary: pd.DataFrame +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Resolves checkbox logic. + + By default, a cell is marked as 'Unchecked' in the absence of the positive, even if the question was not asked to the subjid. If the question was not asked to the subjid because of the branching logic, then set this to be NaN instead. This does not completely check the branching logic, - which is a data quality issue!""" + which is a data quality issue!. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The REDCap data dictionary. + + Returns + ------- + pd.DataFrame + The data with the checkbox branching logic resolved. + """ checkbox_ind = dictionary.loc[(dictionary["field_type"] == "checkbox")] branching_logic_variables = dictionary["branching_logic"].apply( get_branching_logic_variables ) + for ind in checkbox_ind.index: branching_logic_columns = [ - col for col in df.columns if col in branching_logic_variables.loc[ind] + col for col in data.columns if col in branching_logic_variables.loc[ind] ] - remove_ind = df[branching_logic_columns].isna().any(axis=1) + remove_ind = data[branching_logic_columns].isna().any(axis=1) checkbox_columns = [ col - for col in df.columns + for col in data.columns if (col.split("___")[0] == dictionary.loc[ind, "field_name"]) ] - df.loc[remove_ind, checkbox_columns] = np.nan - return df - - -def harmonise_age(df, age_columns=["demog_age", "demog_age_units"]): - """Deprecated, age should now be included in conversion_table.csv. - Convert age from any units into age in years.""" - df = df.rename(columns=dict(zip(age_columns, ["demog_age", "demog_age_units"]))) - df.loc[:, "demog_age"] = pd.to_numeric(df["demog_age"], errors="coerce") - df.loc[:, "demog_age"] = df["demog_age"].astype(float) - df.loc[(df["demog_age_units"] == "Months"), "demog_age"] *= 1 / 12 - df.loc[(df["demog_age_units"] == "Days"), "demog_age"] *= 1 / 365 + data.loc[remove_ind, checkbox_columns] = np.nan + + return data + + +def harmonise_age( + data: pd.DataFrame, + age_columns: typing.Iterable[str] = ["demog_age", "demog_age_units"], +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : The data with ages harmonised. + + .. warning:: + + DEPRECATED. Age should now be included in `conversion_table.csv`. + Convert age from any units into age in years. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + age_columns : typing.Iterable, default=["demog_age", "demog_age_units"] + An iterable (e.g. list) of age columns. + + Returns + ------- + pd.DataFrame + The data with ages harmonised. + """ + warnings.warn( + ( + "`redcap_data.harmonise_age` is deprecated. " + "Age should now be included in `conversion_table.csv`. " + "Convert age from any units into age in years." + ), + DeprecationWarning, + stacklevel=2, + ) + + data = data.rename(columns=dict(zip(age_columns, ["demog_age", "demog_age_units"]))) + data.loc[:, "demog_age"] = pd.to_numeric(data["demog_age"], errors="coerce") + data.loc[:, "demog_age"] = data["demog_age"].astype(float) + data.loc[(data["demog_age_units"] == "Months"), "demog_age"] *= 1 / 12 + data.loc[(data["demog_age_units"] == "Days"), "demog_age"] *= 1 / 365 unit_list = ["Days", "Months", "Years"] # Standardize the units to 'Years' - df.loc[df["demog_age_units"].isin(unit_list), "demog_age_units"] = "Years" - return df + data.loc[data["demog_age_units"].isin(unit_list), "demog_age_units"] = "Years" + + return data + + +def map_variable( + variable: pd.Series, + mapping_dict: dict[str, typing.Any], + non_nan_value: str = "Other / Unknown", +) -> pd.Series: + """:py:class:`pd.Series` : Map a variable column using a dict. + + Any non-NaN value not in the dict keys is converted to the value specified + by ``other_value_str``. + + Parameters + ---------- + variable : pd.Series + The variable column to map. + mapping_dict : dict + The mapping dict. -def map_variable(variable, mapping_dict, other_value_str="Other / Unknown"): - """Map a variable according to a dict. Any non-NaN value not in the dict - keys is converted to other_value_str.""" - other_value_ind = (variable.isin(mapping_dict.keys()) == 0) & variable.notna() + non_nan_value : str, default="Other / Unknown" + Optional value with which to replace non-NaN values not in the dict + keys. + """ + non_nan_value_ind = (variable.isin(mapping_dict.keys()) == 0) & variable.notna() variable = variable.map(mapping_dict) - variable.loc[other_value_ind] = other_value_str + variable.loc[non_nan_value_ind] = non_nan_value + return variable @@ -605,19 +1151,26 @@ def load_countries_table(encoding: str = "latin-1") -> pd.DataFrame: ) -def homogenise_variables(df, dictionary): - """ - Converts variables in a DataFrame based on a conversion table. +def homogenise_variables( + data: pd.DataFrame, dictionary: pd.DataFrame +) -> tuple[pd.DataFrame]: + """:py:class:`pd.DataFrame` : Converts variables in given units in the data based on a conversion table. - Parameters: - df: DataFrame containing values and their units. - conversion_table: DataFrame containing conversion specifications. + Parameters + ---------- + data : pd.DataFrame + The incoming data. - Returns: - pd.DataFrame: DataFrame with all specified values converted to the - desired units. - """ + dictionary : pd.DataFrame + Conversion table/dictionary, as a Pandas dataframe. + + Returns + ------- + pd.DataFrame + The data with unit conversions applied. + """ # noqa : E501 conversion_table = load_units_conversion_table() + for index, row in conversion_table.iterrows(): from_unit = row["from_unit"] to_unit = row["to_unit"] @@ -627,7 +1180,7 @@ def homogenise_variables(df, dictionary): try: # Ensure that the value column is numeric - df.loc[:, value_col] = pd.to_numeric(df[value_col], errors="coerce") + data.loc[:, value_col] = pd.to_numeric(data[value_col], errors="coerce") # Check if the variable is labs_lymphocyte or labs_neutrophil check_ind = ( @@ -638,51 +1191,71 @@ def homogenise_variables(df, dictionary): if check_ind: # Convert absolute count to percentage using total WBC count total_wbc_col = "labs_wbccount" - if total_wbc_col in df.columns: + if total_wbc_col in data.columns: # Ensure the total WBC count column is numeric - df.loc[:, total_wbc_col] = pd.to_numeric( - df[total_wbc_col], errors="coerce" + data.loc[:, total_wbc_col] = pd.to_numeric( + data[total_wbc_col], errors="coerce" ) # Apply conversion only to non-empty values mask = ( - (df[unit_col] == from_unit) - & df[value_col].notna() - & df[total_wbc_col].notna() + (data[unit_col] == from_unit) + & data[value_col].notna() + & data[total_wbc_col].notna() ) - df.loc[mask, value_col] = 100 * ( - df.loc[mask, value_col] / df.loc[mask, total_wbc_col] + data.loc[mask, value_col] = 100 * ( + data.loc[mask, value_col] / data.loc[mask, total_wbc_col] ) - df.loc[mask, unit_col] = to_unit + data.loc[mask, unit_col] = to_unit continue # Only apply the conversion if the factor is not NaN and the # value_col is not empty if not pd.isna(conversion_factor): - mask = (df[unit_col] == from_unit) & df[value_col].notna() + mask = (data[unit_col] == from_unit) & data[value_col].notna() # Apply the conversion - df.loc[mask, value_col] *= conversion_factor + data.loc[mask, value_col] *= conversion_factor # Set all units to the target unit - df.loc[df[unit_col] == from_unit, unit_col] = to_unit + data.loc[data[unit_col] == from_unit, unit_col] = to_unit dictionary_ind = dictionary["field_name"] == value_col dictionary.loc[dictionary_ind, "field_label"] += f" ({to_unit})" except Exception: pass + if "demog_age" not in conversion_table["variable"]: try: - df = harmonise_age(df) + data = harmonise_age(data) except Exception: pass - return df, dictionary + return data, dictionary + + +def convert_onehot_to_binary( + data: pd.DataFrame, dictionary: pd.DataFrame +) -> pd.DataFrame: + """:py:class:`pd.DataFrame` : Converts onehot-encoded columns in the data. + + The conversions will be True/False/NaN values, and answers from the data + dictionary discarded if they exist. + + Parameters + ---------- + data : pd.DataFrame + The incoming data. + + dictionary : pd.DataFrame + The REDCap data dictionary. -def convert_onehot_to_binary(df, dictionary): - """Convert onehot-encoded columns to True/False/NaN and discard answers - from the data dictionary, if they exist.""" + Returns + ------- + pd.DataFrame + The data with the one-hot columns appropriately converted. + """ binary_ind = dictionary["field_type"] == "binary" binary_columns = dictionary.loc[binary_ind, "field_name"].tolist() - binary_columns = [col for col in binary_columns if col in df.columns] + binary_columns = [col for col in binary_columns if col in data.columns] mapping_dict = { "Yes": True, "Checked": True, @@ -691,20 +1264,43 @@ def convert_onehot_to_binary(df, dictionary): "Unknown": np.nan, } with pd.option_context("future.no_silent_downcasting", True): - df.loc[:, binary_columns] = df[binary_columns].replace(mapping_dict) - return df + data.loc[:, binary_columns] = data[binary_columns].replace(mapping_dict) + + return data ############################################ -# Main functions +# Initial data processing ############################################ -def initial_data_processing(data, dictionary, missing_data_codes): - """Initial processing of complete pandas dataframe, after REDCAP API call""" +def initial_data_processing( + data: pd.DataFrame, + dictionary: pd.DataFrame, + missing_data_codes: dict[str, typing.Any], +) -> tuple[pd.DataFrame]: + """:py:class:`tuple` : Initial processing function invoked after the REDCap API call. + + Parameters + ---------- + data : pd.DataFrame + The incoming REDCap data. + + dictionary : pd.DataFrame + The REDCap data dictionary. + + missing_data_codes : dict + The dict of missing code keys and values. + + Returns + ------- + tuple + A tuple consisting of the updated data and data dictionary dataframes. + """ # noqa : E501 # Replace empty cells or 'Unknown' with NaN with pd.option_context("future.no_silent_downcasting", True): data = data.replace(["", "Unknown", "unknown"], np.nan) + # Replace missing data codes with NaN if missing_data_codes is not None: with pd.option_context("future.no_silent_downcasting", True): @@ -791,8 +1387,25 @@ def initial_data_processing(data, dictionary, missing_data_codes): return data, new_dictionary -def get_df_map(data, dictionary): - """Convert single-event rows into one row per patient.""" +def get_df_map( + data: pd.DataFrame, dictionary: pd.DataFrame +) -> tuple[pd.DataFrame | dict[str, typing.Any]]: + """:py:class:`pd.DataFrame` : Returns a dataframe with single-event rows converted to a format with one row per patient. + + Parameters + ---------- + data : pd.DataFrame + The incoming REDCap data. + + dictionary : pd.DataFrame + The REDCap data. + + Returns + ------- + tuple + Three dataframes, consisting of the transformed data. the data + dictionary, and the quality report. + """ # noqa : E501 df_map = data.copy() forms = ["presentation", "daily", "outcome"] columns = dictionary.loc[dictionary["form_name"].isin(forms), "field_name"].tolist() @@ -850,12 +1463,31 @@ def get_df_map(data, dictionary): dictionary = pd.concat([dictionary, pd.DataFrame.from_dict(outcome_dict)], axis=0) dictionary = dictionary.reset_index(drop=True) logger.debug(f"Data contains {df_map.shape[0]} patients") + return df_map, dictionary, quality_report -def get_df_forms(data, dictionary): +def get_df_forms( + data: pd.DataFrame, dictionary: pd.DataFrame +) -> dict[str, pd.DataFrame]: + """:py:class:`dict` : Returns a dict of clinical form names and associated dataframes. + + Parameters + ---------- + data : pd.DataFrame + The incoming REDCap data. + + dictionary : pd.DataFrame + The data dictionary. + + Returns + ------- + dict + The dict of clinical form names and associated dataframes. + """ # noqa : E501 forms = dictionary["form_name"].unique() df_forms_dict = {} + for form in forms: columns = dictionary.loc[dictionary["form_name"] == form, "field_name"].tolist() columns = [col for col in columns if col in data.columns] @@ -863,17 +1495,36 @@ def get_df_forms(data, dictionary): columns = ["subjid"] + columns ind = data["form_name"].apply(lambda x: form in x.split(",")) df_forms_dict[form] = data.loc[ind, columns].reset_index(drop=True) + return df_forms_dict def get_redcap_data( - redcap_url, - redcap_api_key, - data_access_groups=None, - user_assigned_to_dag=False, - country_mapping=None, -): - """Get data from REDCap API and transform into analysis-ready dataframes""" + redcap_url: str, + redcap_api_key: str, + data_access_groups: typing.Iterable[str] | None = None, + user_assigned_to_dag: bool | None = False, + country_mapping: dict | None = None, +) -> tuple[pd.DataFrame | dict[str, pd.DataFrame] | dict[str, typing.Any]]: + """:py:class:`tuple` : Returns data from REDCap API and transforms them into analysis-ready dataframes. + + Parameters + ---------- + redcap_url : str + The REDCap database URL. + + redcap_api_key : str + The REDCap API key. + + data_access_groups : typing.Iterable, default=None + Optional iterable of data access group (DAG) names. + + user_assigned_to_dag : bool, default=None + Whether the user is assigned to a DAG. + + country_mapping : dict + The countries table. + """ # noqa : E501 total_started = time.perf_counter() logger.info("REDCap data pipeline start") diff --git a/isaricanalytics/visualisation.py b/isaricanalytics/visualisation.py index 3c45afa..241dff8 100644 --- a/isaricanalytics/visualisation.py +++ b/isaricanalytics/visualisation.py @@ -1,3 +1,5 @@ +from __future__ import annotations + __all__ = [ "fig_bar_chart", "fig_bar_line_chart", From fd9c300f4b74ed89d2b92643522a53b55a776aa5 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Tue, 5 May 2026 15:01:56 +0100 Subject: [PATCH 15/34] docs: initial version of Sphinx docs with complete API reference --- docs/index.rst | 48 +++++++++++++++---- docs/sources/api-reference.rst | 15 ++++++ docs/sources/isaricanalytics/analytics.rst | 7 +++ docs/sources/isaricanalytics/redcap_data.rst | 7 +++ docs/sources/isaricanalytics/utils.rst | 7 +++ .../sources/isaricanalytics/visualisation.rst | 7 +++ 6 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 docs/sources/api-reference.rst create mode 100644 docs/sources/isaricanalytics/analytics.rst create mode 100644 docs/sources/isaricanalytics/redcap_data.rst create mode 100644 docs/sources/isaricanalytics/utils.rst create mode 100644 docs/sources/isaricanalytics/visualisation.rst diff --git a/docs/index.rst b/docs/index.rst index fdcea06..70d820c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,16 +1,44 @@ -.. isaricanalytics documentation master file, created by - sphinx-quickstart on Wed Apr 8 09:51:09 2026. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +=============== +isaricanalytics +=============== -isaricanalytics documentation -============================= +ISARIC Analytics library for users requiring or interested in: -Add your content using ``reStructuredText`` syntax. See the -`reStructuredText `_ -documentation for details. +- REDCap data extraction +- ISARIC data analytics +- ISARIC data visualisation +Installation +------------ + +Install with :program:`pip` directly from `GitHub `_ using: + +.. code:: shell + + pip install -U git+https://github.com/ISARICResearch/ISARICAnalytics + +This will install the default ``main`` branch of the repo - if you want a specific branch, tag or commit SHA use + +.. code:: shell + + pip install -U git+https://github.com/ISARICResearch/ISARICAnalytics@ + +The minimum required Python version is 3.12. + +Documentation +------------- .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :caption: Contents: + + The documentation is currently limited to an API reference for all the core public libraries, but user tutorials and additional documentation may be added in the future. + + sources/api-reference + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/sources/api-reference.rst b/docs/sources/api-reference.rst new file mode 100644 index 0000000..a7eac73 --- /dev/null +++ b/docs/sources/api-reference.rst @@ -0,0 +1,15 @@ +============= +API Reference +============= + +``isaricanalytics`` API reference. + +.. toctree:: + :maxdepth: 1 + :name: api_reference_toc + :caption: Contents: + + isaricanalytics/redcap_data + isaricanalytics/analytics + isaricanalytics/visualisation + isaricanalytics/utils diff --git a/docs/sources/isaricanalytics/analytics.rst b/docs/sources/isaricanalytics/analytics.rst new file mode 100644 index 0000000..64f152d --- /dev/null +++ b/docs/sources/isaricanalytics/analytics.rst @@ -0,0 +1,7 @@ +============================= +``isaricanalytics.analytics`` +============================= + +.. automodule:: isaricanalytics.analytics + :members: + :special-members: diff --git a/docs/sources/isaricanalytics/redcap_data.rst b/docs/sources/isaricanalytics/redcap_data.rst new file mode 100644 index 0000000..ed2f066 --- /dev/null +++ b/docs/sources/isaricanalytics/redcap_data.rst @@ -0,0 +1,7 @@ +=============================== +``isaricanalytics.redcap_data`` +=============================== + +.. automodule:: isaricanalytics.redcap_data + :members: + :special-members: diff --git a/docs/sources/isaricanalytics/utils.rst b/docs/sources/isaricanalytics/utils.rst new file mode 100644 index 0000000..9bbf295 --- /dev/null +++ b/docs/sources/isaricanalytics/utils.rst @@ -0,0 +1,7 @@ +========================= +``isaricanalytics.utils`` +========================= + +.. automodule:: isaricanalytics.utils + :members: + :special-members: diff --git a/docs/sources/isaricanalytics/visualisation.rst b/docs/sources/isaricanalytics/visualisation.rst new file mode 100644 index 0000000..56b1557 --- /dev/null +++ b/docs/sources/isaricanalytics/visualisation.rst @@ -0,0 +1,7 @@ +================================= +``isaricanalytics.visualisation`` +================================= + +.. automodule:: isaricanalytics.visualisation + :members: + :special-members: From ee68afeb43e415c7b7176daf5579aaadadb58986 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Tue, 5 May 2026 15:08:08 +0100 Subject: [PATCH 16/34] Refresh RTD PR build From be22f38477b89aeced4b093ee0f23fe433ca1970 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Tue, 5 May 2026 15:56:28 +0100 Subject: [PATCH 17/34] docs: add some more stuff to index RST --- docs/index.rst | 8 +++++--- docs/sources/contributing.rst | 9 +++++++++ docs/sources/visualisation.rst | 9 +++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 docs/sources/contributing.rst create mode 100644 docs/sources/visualisation.rst diff --git a/docs/index.rst b/docs/index.rst index 70d820c..af93016 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,7 +17,7 @@ Install with :program:`pip` directly from `GitHub Date: Wed, 6 May 2026 09:58:09 +0100 Subject: [PATCH 18/34] docs: enable light mode and turn off dark mode --- docs/conf.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++--- docs/index.rst | 12 +++++----- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 57bfca4..e433a2e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -150,7 +150,7 @@ ] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" +# pygments_style = "sphinx" # A list of prefixes that are ignored when creating the module index. # (new in Sphinx 0.6) @@ -193,7 +193,61 @@ # HTML theme options html_theme = "furo" -html_theme_options = {} +html_theme_options = { + # Since Furo doesn't allow us to disable dark mode, we make dark mode + # equivalent to light mode by overriding all colors back to their light value. + # See: https://github.com/pradyunsg/furo/issues/28 + 'dark_css_variables': { + # Taken from: https://github.com/pradyunsg/furo/blob/c682d5d3502f3fa713c909eebbf9f3afa0f469d9/src/furo/assets/styles/variables/_colors.scss + 'color-problematic': '#b30000', + + # Base Colors + 'color-foreground-primary': 'black', # for main text and headings + 'color-foreground-secondary': '#5a5c63', # for secondary text + 'color-foreground-muted': '#646776', # for muted text + 'color-foreground-border': '#878787', # for content borders + + 'color-background-primary': 'white', # for content + 'color-background-secondary': '#f8f9fb', # for navigation + ToC + 'color-background-hover': '#efeff4ff', # for navigation-item hover + 'color-background-hover--transparent': '#efeff400', + 'color-background-border': '#eeebee', # for UI borders + 'color-background-item': '#ccc', # for "background" items (eg: copybutton) + + # Announcements + 'color-announcement-background': '#000000dd', + 'color-announcement-text': '#eeebee', + + # Brand colors + 'color-brand-primary': '#2962ff', + 'color-brand-content': '#2a5adf', + + # Highlighted text (search) + 'color-highlighted-background': '#ddeeff', + + # GUI Labels + 'color-guilabel-background': '#ddeeff80', + 'color-guilabel-border': '#bedaf580', + + # API documentation + 'color-api-keyword': 'var(--color-foreground-secondary)', + 'color-highlight-on-target': '#ffffcc', + + # Admonitions + 'color-admonition-background': 'transparent', + + # Cards + 'color-card-border': 'var(--color-background-secondary)', + 'color-card-background': 'transparent', + 'color-card-marginals-background': 'var(--color-background-hover)', + + # Code blocks + 'color-code-foreground': 'black', + 'color-code-background': '#f8f9fb', + } +} +# Force pygments style in dark mode back to the light variant +pygments_dark_style = 'tango' # html_logo = '_static/logo.png' @@ -206,7 +260,9 @@ # # https://sphinx-design.readthedocs.io/en/latest/badges_buttons.html#fontawesome-icons # -# html_css_files = [] +html_css_files = [ + "css/custom.css", +] # Timestamp format for the last page updated time html_last_updated_fmt = "%b %d, %Y" diff --git a/docs/index.rst b/docs/index.rst index af93016..2bee34d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,8 +1,8 @@ -=============== -isaricanalytics -=============== +================ +ISARIC Analytics +================ -ISARIC Analytics library for users requiring or interested in: +The `ISARIC Analytics `_ library (:code:`isaricanalytics`) is for users requiring or interested in: - REDCap data extraction - ISARIC data analytics @@ -11,7 +11,7 @@ ISARIC Analytics library for users requiring or interested in: Installation ------------ -Install with :program:`pip` directly from `GitHub `_ using: +Install with :program:`pip` directly from GitHub using: .. code:: shell @@ -28,7 +28,7 @@ The minimum required Python version is 3.12. Documentation ------------- -The documentation is currently limited to an API reference for all the core public libraries, but user tutorials and additional documentation may be added in the future. +The documentation is currently limited to an API reference for all the core public libraries, but user tutorials, a visualisation gallery and additional documentation will be added in the future. .. toctree:: :maxdepth: 1 From 78ba1c0758e5340ca429a802b70a71a8857d1b12 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Wed, 6 May 2026 11:45:02 +0100 Subject: [PATCH 19/34] lint --- docs/conf.py | 66 ++++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index e433a2e..faa466d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -197,57 +197,47 @@ # Since Furo doesn't allow us to disable dark mode, we make dark mode # equivalent to light mode by overriding all colors back to their light value. # See: https://github.com/pradyunsg/furo/issues/28 - 'dark_css_variables': { + "dark_css_variables": { # Taken from: https://github.com/pradyunsg/furo/blob/c682d5d3502f3fa713c909eebbf9f3afa0f469d9/src/furo/assets/styles/variables/_colors.scss - 'color-problematic': '#b30000', - + "color-problematic": "#b30000", # Base Colors - 'color-foreground-primary': 'black', # for main text and headings - 'color-foreground-secondary': '#5a5c63', # for secondary text - 'color-foreground-muted': '#646776', # for muted text - 'color-foreground-border': '#878787', # for content borders - - 'color-background-primary': 'white', # for content - 'color-background-secondary': '#f8f9fb', # for navigation + ToC - 'color-background-hover': '#efeff4ff', # for navigation-item hover - 'color-background-hover--transparent': '#efeff400', - 'color-background-border': '#eeebee', # for UI borders - 'color-background-item': '#ccc', # for "background" items (eg: copybutton) - + "color-foreground-primary": "black", # for main text and headings + "color-foreground-secondary": "#5a5c63", # for secondary text + "color-foreground-muted": "#646776", # for muted text + "color-foreground-border": "#878787", # for content borders + "color-background-primary": "white", # for content + "color-background-secondary": "#f8f9fb", # for navigation + ToC + "color-background-hover": "#efeff4ff", # for navigation-item hover + "color-background-hover--transparent": "#efeff400", + "color-background-border": "#eeebee", # for UI borders + "color-background-item": "#ccc", # for "background" items (eg: copybutton) # Announcements - 'color-announcement-background': '#000000dd', - 'color-announcement-text': '#eeebee', - + "color-announcement-background": "#000000dd", + "color-announcement-text": "#eeebee", # Brand colors - 'color-brand-primary': '#2962ff', - 'color-brand-content': '#2a5adf', - + "color-brand-primary": "#2962ff", + "color-brand-content": "#2a5adf", # Highlighted text (search) - 'color-highlighted-background': '#ddeeff', - + "color-highlighted-background": "#ddeeff", # GUI Labels - 'color-guilabel-background': '#ddeeff80', - 'color-guilabel-border': '#bedaf580', - + "color-guilabel-background": "#ddeeff80", + "color-guilabel-border": "#bedaf580", # API documentation - 'color-api-keyword': 'var(--color-foreground-secondary)', - 'color-highlight-on-target': '#ffffcc', - + "color-api-keyword": "var(--color-foreground-secondary)", + "color-highlight-on-target": "#ffffcc", # Admonitions - 'color-admonition-background': 'transparent', - + "color-admonition-background": "transparent", # Cards - 'color-card-border': 'var(--color-background-secondary)', - 'color-card-background': 'transparent', - 'color-card-marginals-background': 'var(--color-background-hover)', - + "color-card-border": "var(--color-background-secondary)", + "color-card-background": "transparent", + "color-card-marginals-background": "var(--color-background-hover)", # Code blocks - 'color-code-foreground': 'black', - 'color-code-background': '#f8f9fb', + "color-code-foreground": "black", + "color-code-background": "#f8f9fb", } } # Force pygments style in dark mode back to the light variant -pygments_dark_style = 'tango' +pygments_dark_style = "tango" # html_logo = '_static/logo.png' From 3d78b72cab61c0a059a7853acfc50cdee0d3754b Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Wed, 6 May 2026 13:02:15 +0100 Subject: [PATCH 20/34] test: update conversion table --- tests/unit/assets/conversion_table.csv | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/unit/assets/conversion_table.csv b/tests/unit/assets/conversion_table.csv index 71db60a..1dbf5c2 100644 --- a/tests/unit/assets/conversion_table.csv +++ b/tests/unit/assets/conversion_table.csv @@ -1,14 +1,14 @@ -from_unit,to_unit,variable,variable_unit,conversion_factor -umol/L,mg/dL,labs_creatinine,labs_creatinine_units,88.4 -mmol/L,mg/dL,labs_ureanitro,labs_ureanitro_units,0.357 -10^9/L,%,labs_neutrophil,labs_neutrophil_units, -C,F,vital_highesttem,vital_highesttem_units,1.8 -umol/L,mg/dL,labs_bilirubin,labs_bilirubin_units,17.1 -10^9/L,%,labs_lymphocyte,labs_lymphocyte_units, -"Fraction, 0.21-1.0","%, 21-100",vital_fio2spo2,vital_fio2spo2_units,100.0 -mg,mmol/L,labs_lactate,labs_lactate_units,0.0555 -mEq/L,mmol/L,labs_hco3,labs_hco3_units,1.0 -L/L,%,labs_hematocrit,labs_hematocrit_units,100.0 -mg/dL,ng/mL,labs_tropi,labs_tropi_units,10000.0 -mmol/L,Not done,comor_hba1c,comor_hba1c_units,1.0 -g/L,g/dL,labs_haemo,labs_haemo_units,10.0 +from_unit,to_unit,variable,variable_unit,conversion_factor,conversion_offset +umol/L,mg/dL,labs_creatinine,labs_creatinine_units,88.4,0 +mmol/L,mg/dL,labs_ureanitro,labs_ureanitro_units,0.357,0 +10^9/L,%,labs_neutrophil,labs_neutrophil_units,, +F,C,vital_highesttem,vital_highesttem_units,0.5556,-17.7778 +umol/L,mg/dL,labs_bilirubin,labs_bilirubin_units,17.1,0 +10^9/L,%,labs_lymphocyte,labs_lymphocyte_units,, +"Fraction, 0.21-1.0","%, 21-100",vital_fio2spo2,vital_fio2spo2_units,100.0,0 +mg,mmol/L,labs_lactate,labs_lactate_units,0.0555,0 +mEq/L,mmol/L,labs_hco3,labs_hco3_units,1.0,0 +L/L,%,labs_hematocrit,labs_hematocrit_units,100.0,0 +mg/dL,ng/mL,labs_tropi,labs_tropi_units,10000.0,0 +mmol/L,Not done,comor_hba1c,comor_hba1c_units,1.0,0 +g/L,g/dL,labs_haemo,labs_haemo_units,10.0,0 From 22d21a4300b1ed032bff9113301f8444004ca5e2 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Thu, 7 May 2026 08:59:38 +0100 Subject: [PATCH 21/34] chore: switch license to MIT and add citation file --- CITATION.cff | 40 ++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 1 - 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 CITATION.cff diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..622a5bf --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,40 @@ +cff-version: 1.2.0 +title: IsaricAnalytics +message: Data analysis toolkit to support fast analysis of clinical data during emerging infectious disease outbreaks. +type: software +authors: + - name-particle: Tom + family-names: Edinburgh + email: tom.edinburgh@ndm.ox.ac.uk + orcid: 0000-0002-3599-7133 + - name-particle: Esteban + family-names: Garcia-Gallo + email: esteban.garcia@ndm.ox.ac.uk + orcid: 0000-0002-8030-9985 + - name-particle: Igor + family-names: Peres + email: igor.peres@puc-rio.br + orcid: + - name-particle: Tomoe + family-names: Gusberti + email: tomoegusberti@gmail.com + orcid: + - name-particle: Luiz + family-names: Raffaini + email: lemraffaini@gmail.com + orcid: +repository-code: 'https://github.com/ISARICResearch/IsaricAnalytics' +url: 'https://github.com/ISARICResearch/IsaricAnalytics' +abstract: Data analysis toolkit to support fast analysis of clinical data during emerging infectious disease outbreaks. +keywords: + - isaric + - infectious disease + - pandemic + - disease outbreak + - clinical epidemiology + - disease outbreak response + - data analysis + - data analytics +license: MIT +version: 0.2.0 +date-released: diff --git a/pyproject.toml b/pyproject.toml index ab495cd..6d72d91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,6 @@ authors = [ { name = "Carlos Lima", email = "carlos.jlima@ufpe.br" }, { name = "Tomoe Gusberti", email = "tomoegusberti@gmail.com" }, { name = "Luiz Raffaini", email = "lemraffaini@gmail.com" }, - { name = "Sandeep Murthy", email = "sandeep.murthy@ndm.ox.ac.uk" } ] maintainers = [ From a3cf37188a7368f9a1b0027a5f188ef3b151f278 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 09:46:29 +0100 Subject: [PATCH 22/34] ci: tidy up workflow chaining for test and build workflows --- .github/workflows/build.yml | 1 + .github/workflows/test.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b422605..be82871 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,6 +12,7 @@ on: jobs: build: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} timeout-minutes: 30 steps: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 488077d..248648f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,7 @@ on: jobs: unit-test: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} timeout-minutes: 30 steps: From c02929ae1fb50f850f07c33d0b5a7c1d50b8f2df Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 09:58:07 +0100 Subject: [PATCH 23/34] docs: remove static `docs/requirements.txt` + enable docs deps installation via RTD YML --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index faa466d..ea15804 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -102,9 +102,9 @@ # https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_default_options autodoc_default_options = { "exclude-members": "", - "member-order": "bysource", + "member-order": "alphabetical", "private-members": False, - "special-members": "__init__,__new__", + "special-members": } # Sphinx autodoc autosummary settings From e867ce6c96b6cf47b5dbcfe32a816ce03f03bc90 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 10:00:03 +0100 Subject: [PATCH 24/34] chore: add PyPI classifiers to project TOML --- pyproject.toml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 6d72d91..ff4eba4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,24 @@ keywords = [ "data-analysis", "data-analytics", ] + + +# Not strictly required as this isn't a public Python package, but still good +# to have. +classifiers = [ + "Environment :: Console", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Development Status :: 5 - Production/Stable", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows", +] + requires-python = ">=3.11" dependencies = [ "lifelines==0.30.0", From a494f38e31e70524ee4d87a91f11cf15086bd659 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 10:01:56 +0100 Subject: [PATCH 25/34] linting fix --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index ea15804..15aade4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -104,7 +104,7 @@ "exclude-members": "", "member-order": "alphabetical", "private-members": False, - "special-members": + "special-members": "", } # Sphinx autodoc autosummary settings From af9cad3a31ebea78910ad3aaa417d488541a5bf8 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 10:08:56 +0100 Subject: [PATCH 26/34] docs: add placeholder pages for analytics and REDCap data extraction guides --- docs/index.rst | 4 +++- docs/sources/analytics.rst | 9 +++++++++ docs/sources/redcap-data.rst | 9 +++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 docs/sources/analytics.rst create mode 100644 docs/sources/redcap-data.rst diff --git a/docs/index.rst b/docs/index.rst index 2bee34d..16f1b44 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,7 +23,7 @@ This will install the default ``main`` branch of the repo, including all package pip install -U git+https://github.com/ISARICResearch/ISARICAnalytics@ -The minimum required Python version is 3.12. +The minimum required Python version is 3.11. Documentation ------------- @@ -35,6 +35,8 @@ The documentation is currently limited to an API reference for all the core publ :caption: Contents: sources/api-reference + sources/redcap-data + sources/analytics sources/visualisation sources/contributing diff --git a/docs/sources/analytics.rst b/docs/sources/analytics.rst new file mode 100644 index 0000000..76615bb --- /dev/null +++ b/docs/sources/analytics.rst @@ -0,0 +1,9 @@ +========= +Analytics +========= + +A guide to ISARIC data analytics. + +.. todo:: + + TODO diff --git a/docs/sources/redcap-data.rst b/docs/sources/redcap-data.rst new file mode 100644 index 0000000..f68b301 --- /dev/null +++ b/docs/sources/redcap-data.rst @@ -0,0 +1,9 @@ +=========== +REDCap Data +=========== + +A guide to REDCap data extraction. + +.. todo:: + + TODO From c96fdf166e42e345963f2cde3544cbd26ad6783a Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 11:39:52 +0100 Subject: [PATCH 27/34] docs: fix Intersphinx problem with the Plotly docs domain + docstring RST fixes in al core libs --- docs/conf.py | 35 +++ isaricanalytics/analytics.py | 358 +++++++++++++++---------------- isaricanalytics/redcap_data.py | 180 ++++++++-------- isaricanalytics/utils.py | 8 +- isaricanalytics/visualisation.py | 215 ++++++++++--------- 5 files changed, 420 insertions(+), 376 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 15aade4..7b3f7d2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,6 +10,12 @@ from datetime import datetime # -- 3rd party libraries -- +from docutils import nodes +from sphinx.addnodes import pending_xref +from sphinx.application import Sphinx +from sphinx.environment import BuildEnvironment +from sphinx.ext.intersphinx import missing_reference + # -- Internal libraries -- import isaricanalytics from isaricanalytics import __version__ @@ -124,6 +130,7 @@ #'dash': ('https://dash.plotly.com/', None), "numpy": ("https://numpy.org/doc/stable/", None), "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), + "plotly": ("https://plotly.com/python-api-reference/", None), "Python": ("https://docs.python.org/3", None), "scikit-learn": ("https://scikit-learn.org/stable/", None), "scipy": ("https://docs.scipy.org/doc/scipy/", None), @@ -131,6 +138,34 @@ "statsmodels": ("https://www.statsmodels.org/stable", None), } + +# A custom solution from: +# +# https://stackoverflow.com/questions/73528299/link-to-plotly-graph-objects-figure-with-intersphinx +# +# to handle Intersphinx problems with the Plotly domain. +def fix_reference( + app: Sphinx, env: BuildEnvironment, node: pending_xref, contnode: nodes.TextElement +) -> nodes.reference | None: + """ + Fix some intersphinx references that are broken. + """ + if node["refdomain"] == "py": + # strange imports in plotly require a hardcoded redirect + if node["reftarget"] == "plotly.graph_objs._figure.Figure": + node["reftarget"] = "plotly.graph_objects.Figure" + return missing_reference(app, env, node, contnode) + + return None + + +def setup(app: Sphinx) -> None: + """ + Force sphinx to fix additional things on setup. + """ + app.connect("missing-reference", fix_reference) + + # Static template paths templates_path = ["_templates"] diff --git a/isaricanalytics/analytics.py b/isaricanalytics/analytics.py index 621131c..68841e3 100644 --- a/isaricanalytics/analytics.py +++ b/isaricanalytics/analytics.py @@ -1,7 +1,6 @@ from __future__ import annotations __all__ = [ - "classification_report", "convert_categorical_to_onehot", "convert_onehot_to_categorical", "create_grouped_results", @@ -53,7 +52,7 @@ # -- 3rd party libraries -- import numpy as np -import pandas as pd +import pandas import statsmodels.api as sm import statsmodels.formula.api as smf from lifelines import CoxPHFitter, KaplanMeierFitter @@ -68,6 +67,10 @@ # -- Internal libraries -- + +pd = pandas # An alias to allow Pandas code refs to work independently +# of Pandas Intersphinx refs in type hinting and docstrings + ############################################ ############################################ # General preprocessing @@ -76,16 +79,16 @@ def extend_dictionary( - dictionary: pd.DataFrame, + dictionary: pandas.DataFrame, new_variable_dict: dict[str, typing.Any], - data: pd.DataFrame, + data: pandas.DataFrame, sep: str = "___", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns the VERTEX dictionary with new custom variables added. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns the VERTEX dictionary with new custom variables added. Parameters ---------- - dictionary : pd.DataFrame) + dictionary : pandas.DataFrame VERTEX dictionary containing columns ``"field_name"``, ``"form_name"``, ``"field_type"``, ``"field_label"``, ``"parent"``, ``"branching_logic"``. @@ -93,7 +96,7 @@ def extend_dictionary( A dict with the same keys as the dictionary columns, the values for each item can be a string or a list. - data : pd.DataFrame + data : pandas.DataFrame Pandas dataframe containing the data for the project. The columns of this dataframe must include the variables in ``new_variable_dict["field_type"]``. @@ -103,7 +106,7 @@ def extend_dictionary( Returns ------- - pd.DataFrame + pandas.DataFrame VERTEX dictionary containing the original variables, plus the new variables and any one-hot-encoded variables derived from this. """ # noqa : E501 @@ -182,8 +185,8 @@ def extend_dictionary( def get_variables_by_section_and_type( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, required_variables: typing.Iterable[str] | None = None, include_sections: typing.Iterable[str] = ["demog"], include_types: typing.Iterable[str] = ["binary", "categorical", "numeric"], @@ -202,10 +205,10 @@ def get_variables_by_section_and_type( Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame Data dictionary. required_variables : typing.Iterable, default=None @@ -258,21 +261,21 @@ def get_variables_by_section_and_type( def convert_categorical_to_onehot( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, categorical_columns: typing.Iterable[str], sep: str = "___", missing_val: str = "nan", drop_first: bool = False, -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns the given dataframe with categorical variable columns converted to onehot-encoded variable columns. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns the given dataframe with categorical variable columns converted to onehot-encoded variable columns. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. categorical_columns : typing.Iterable @@ -291,7 +294,7 @@ def convert_categorical_to_onehot( Returns ------- - pd.DataFrame + pandas.DataFrame The original dataframe with the categorical -> one-hot-encoded variable columns. """ # noqa : E501 @@ -340,20 +343,20 @@ def convert_categorical_to_onehot( def convert_onehot_to_categorical( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, categorical_columns: typing.Iterable[str], sep: str = "___", missing_val: str = "nan", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns the given dataframe with onehot-encoded variable columns to categorical variable columns. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns the given dataframe with onehot-encoded variable columns to categorical variable columns. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame Data dictionary. categorical_columns : typing.Iterable @@ -368,7 +371,7 @@ def convert_onehot_to_categorical( Returns ------- - pd.DataFrame + pandas.DataFrame The original dataframe with the one-hot-encoded -> categorical variable columns. """ # noqa : E501 @@ -399,8 +402,8 @@ def convert_onehot_to_categorical( def from_timeA_to_timeB( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, timeA_column: str, timeB_column: str, timediff_column: str, @@ -411,10 +414,10 @@ def from_timeA_to_timeB( Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. timeA_column : str @@ -472,7 +475,7 @@ def from_timeA_to_timeB( def get_median_interquartile_range( - series: pd.Series, + series: pandas.Series, add_spaces: bool = False, dp: int = 1, mfw: int = 4, @@ -482,7 +485,7 @@ def get_median_interquartile_range( Parameters ---------- - series : pd.Series + series : pandas.Series The input series for which to calculate the IQR. add_spaces : bool, default=False @@ -520,7 +523,7 @@ def get_median_interquartile_range( def median_iqr_str( - series: pd.Series, + series: pandas.Series, add_spaces: bool = False, dp: int = 1, mfw: int = 4, @@ -534,7 +537,7 @@ def median_iqr_str( Parameters ---------- - series : pd.Series + series : pandas.Series The input series for which to calculate the IQR. add_spaces : bool, default=False @@ -569,7 +572,7 @@ def median_iqr_str( def get_mean_and_stdev( - series: pd.Series, + series: pandas.Series, add_spaces: bool = False, dp: int = 1, mfw: int = 4, @@ -579,7 +582,7 @@ def get_mean_and_stdev( Parameters ---------- - series : pd.Series + series : pandas.Series The input series for which to calculate the mean and st. dev. add_spaces : bool, default=False @@ -615,7 +618,7 @@ def get_mean_and_stdev( def mean_std_str( - series: pd.Series, + series: pandas.Series, add_spaces: bool = False, dp: int = 1, mfw: int = 4, @@ -629,7 +632,7 @@ def mean_std_str( Parameters ---------- - series : pd.Series + series : pandas.Series The input series for which to calculate the mean and st. dev. add_spaces : bool, default=False @@ -664,7 +667,7 @@ def mean_std_str( def get_n_percent_value( - series: pd.Series, + series: pandas.Series, add_spaces: bool = False, dp: int = 1, mfw: int = 4, @@ -674,7 +677,7 @@ def get_n_percent_value( Parameters ---------- - series : pd.Series + series : pandas.Series The input series. add_spaces : bool, default=False @@ -714,7 +717,7 @@ def get_n_percent_value( def n_percent_str( - series: pd.Series, + series: pandas.Series, add_spaces: bool = False, dp: int = 1, mfw: int = 4, @@ -728,7 +731,7 @@ def n_percent_str( Parameters ---------- - series : pd.Series + series : pandas.Series The input series. add_spaces : bool, default=False @@ -763,19 +766,19 @@ def n_percent_str( def get_chi2_pvalue( - x: pd.Series, - y: pd.Series, + x: pandas.Series, + y: pandas.Series, x_cat: typing.Iterable[typing.Any] = [True, False], y_cat: typing.Iterable[typing.Any] = [True, False], -) -> float | np.nan: +) -> float: """:py:class:`float` : Returns the :math`p`-value for a Chi-squared test. Parameters ---------- - x : pd.Series + x : pandas.Series The first series/factor. - y : pd.Series + y : pandas.Series The second series/factor. x_cat : typing.Iterable @@ -786,9 +789,8 @@ def get_chi2_pvalue( Returns ------- - float or np.nan - The :math:`p`-value for the test, either a :py:class:`float` or - :py:class:`np.nan`. + float + The :math:`p`-value for the test. """ # noqa : E501 try: print(x.name) @@ -806,8 +808,8 @@ def get_chi2_pvalue( def get_fisher_exact_pvalue( - x: pd.Series, - y: pd.Series, + x: pandas.Series, + y: pandas.Series, x_cat: typing.Iterable[typing.Any] = [True, False], y_cat: typing.Iterable[typing.Any] = [True, False], ): @@ -815,10 +817,10 @@ def get_fisher_exact_pvalue( Parameters ---------- - x : pd.Series + x : pandas.Series The first series/factor. - y : pd.Series + y : pandas.Series The second series/factor. x_cat : typing.Iterable @@ -829,9 +831,8 @@ def get_fisher_exact_pvalue( Returns ------- - float or np.nan - The :math:`p`-value for the test, either a :py:class:`float` or - :py:class:`np.nan`. + float + The :math:`p`-value for the test. """ # noqa : E501 try: contingency = pd.crosstab( @@ -898,8 +899,8 @@ def format_pvalue( def get_descriptive_data( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, by_column: str | None = None, include_sections: typing.Iterable[str] = ["demog"], include_types: typing.Iterable[str] = ["binary", "categorical", "numeric"], @@ -915,15 +916,15 @@ def get_descriptive_data( include_subjid: bool = False, exclude_negatives: bool = True, sep: str = "___", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns descriptive data. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns descriptive data. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame Data dictionary. by_column : str, default=None @@ -954,7 +955,7 @@ def get_descriptive_data( Returns ------- - pd.DataFrame + pandas.DataFrame Returns the descriptive data. """ # noqa : E501 _data = data.copy() @@ -999,25 +1000,25 @@ def get_descriptive_data( def descriptive_table( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, by_column: str | None = None, include_totals: bool = True, column_reorder: typing.Iterable[str] | None = None, include_raw_variable_name: bool = False, sep: str = "___", -) -> tuple[pd.DataFrame, str]: - """:py:class:`py:class:tuple` : Returns the descriptive table and table key for binary and numerical variables in the data. +) -> tuple[pandas.DataFrame, str]: + """:py:class:`tuple` : Returns the descriptive table and table key for binary and numerical variables in the data. The descriptive table will have separate columns for each category that exists for the ``by_column`` variable, if this is provided. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame Data dictionary. by_column : str, default=None @@ -1115,8 +1116,8 @@ def descriptive_table( def descriptive_comparison_table( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, by_column: str | None = None, include_totals: bool = True, column_reorder: typing.Iterable[str] | None = None, @@ -1130,10 +1131,10 @@ def descriptive_comparison_table( Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame Data dictionary. by_column : str, default=None @@ -1272,7 +1273,7 @@ def trim_field_label(x: str, max_len: int = 40) -> str: def format_descriptive_table_variables( - dictionary: pd.DataFrame, + dictionary: pandas.DataFrame, max_len: int = 100, add_key: bool = True, sep: str = "___", @@ -1283,7 +1284,7 @@ def format_descriptive_table_variables( Parameters ---------- - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. max_len : int, default=100 @@ -1334,13 +1335,13 @@ def format_descriptive_table_variables( def format_variables( - dictionary: pd.DataFrame, max_len: int = 40, sep: str = "___" + dictionary: pandas.DataFrame, max_len: int = 40, sep: str = "___" ) -> str: """:py:class:`str` : Returns a formatted string of the descriptive table variable field names. Parameters ---------- - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. max_len : int, default=40 @@ -1387,19 +1388,19 @@ def get_parent_label(x): def get_counts( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, max_n_variables: int = 10, sep: str = "___", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns a dataframe of variable column counts. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns a dataframe of variable column counts. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. max_n_variables : int, default=10 @@ -1431,21 +1432,21 @@ def get_counts( def get_proportions( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, max_n_variables: int = 10, ignore_branching_logic: bool = False, branching_logic: str = "", sep: str = "___", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns a dataframe of proportional counts for variable columns. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns a dataframe of proportional counts for variable columns. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. max_n_variables : int, default=10 @@ -1457,7 +1458,7 @@ def get_proportions( Returns ------- - pd.DataFrame + pandas.DataFrame A dataframe of proportional counts for variable columns. """ # noqa : E501 if ignore_branching_logic: @@ -1511,20 +1512,20 @@ def get_proportions( def get_upset_counts_intersections( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, variables: list[str] | None = None, n_variables: int = 5, sep: str = "___", -) -> tuple[pd.DataFrame]: - """:py:class:`pd.DataFrame` : Returns a dataframe of upset counts intersections. +) -> tuple[pandas.DataFrame]: + """:py:class:`pandas.DataFrame` : Returns a dataframe of upset counts intersections. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. variables : list, default=None @@ -1539,7 +1540,7 @@ def get_upset_counts_intersections( Returns ------- - pd.DataFrame + pandas.DataFrame A dataframe of upset counts intersections. """ # noqa : E501 # Convert variables and column names into their formatted names @@ -1600,16 +1601,16 @@ def get_upset_counts_intersections( def get_pyramid_data( - data: pd.DataFrame, + data: pandas.DataFrame, column_dict: dict[str, str], left_side: str = "Female", right_side: str = "Male", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns dual stack pyramid data. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns dual stack pyramid data. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. column_dict : dict @@ -1625,7 +1626,7 @@ def get_pyramid_data( Returns ------- - pd.DataFrame + pandas.DataFrame Dual stack pyramid data. """ keys = ["side", "y_axis", "stack_group"] @@ -1650,8 +1651,8 @@ def get_pyramid_data( def get_modelling_data( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, outcome_columns: str | typing.Iterable[str], include_sections: typing.Iterable[str] = [ "demog", @@ -1678,15 +1679,15 @@ def get_modelling_data( fillna: bool = True, drop_first: bool = False, sep: str = "___", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns modelling data. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns modelling data. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame Data dictionary. outcome_columns : typing.Iterable @@ -1726,7 +1727,7 @@ def get_modelling_data( Returns ------- - pd.DataFrame + pandas.DataFrame Returns the modelling data. """ # noqa : E501 _data = data.copy() @@ -1774,19 +1775,19 @@ def get_modelling_data( def variance_influence_factor_backwards_elimination( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, predictors_list: typing.Iterable[str], sep: str = "___", -) -> tuple[typing.Iterable[str], pd.DataFrame]: +) -> tuple[typing.Iterable[str], pandas.DataFrame]: """:py:class:`tuple` : Returns an iterable of retained columns and the VIF backwards elimination data. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame Data dictionary. predictors_list : typing.Iterable @@ -1853,8 +1854,8 @@ def variance_influence_factor_backwards_elimination( def remove_single_binary_outcome_predictors( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, predictors: typing.Iterable[str], outcome: str, ) -> typing.Iterable[str]: @@ -1865,10 +1866,10 @@ def remove_single_binary_outcome_predictors( Parameters ---------- - data: pd.DataFrame + data: pandas.DataFrame The incoming data. - dictionary: pd.DataFrame + dictionary: pandas.DataFrame The data dictionary. predictors: typing.Iterable @@ -1909,21 +1910,21 @@ def remove_single_binary_outcome_predictors( def regression_summary_table( - table: pd.DataFrame, - dictionary: pd.DataFrame, + table: pandas.DataFrame, + dictionary: pandas.DataFrame, highlight_predictors: dict[str, typing.Iterable[str]] | None = None, pvalue_significance: float | None = None, result_type: str = "OddsRatio", sep: str = "___", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns a regression summary table. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns a regression summary table. Parameters ---------- - table : pd.DataFrame + table : pandas.DataFrame The incoming table. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. highlight_predictors : dict, default=None @@ -1940,7 +1941,7 @@ def regression_summary_table( Returns ------- - pd.DataFrame + pandas.DataFrame Regression summary table. """ # noqa : E501 # Convert variables and column names into their formatted names @@ -2039,7 +2040,7 @@ def regression_summary_table( def execute_glmm_regression( - elr_dataframe_df: pd.DataFrame, + elr_dataframe_df: pandas.DataFrame, elr_outcome: str, elr_predictors: typing.Iterable[str], elr_groups: str, @@ -2047,12 +2048,12 @@ def execute_glmm_regression( print_results: bool = True, labels: dict[str, str] | None = None, reg_type: str = "multi", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Executes a mixed effects model for linear or logistic regression. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Executes a mixed effects model for linear or logistic regression. Parameters ---------- - elr_dataframe_df : pd.DataFrame + elr_dataframe_df : pandas.DataFrame The incoming data. elr_outcome : str @@ -2082,8 +2083,8 @@ def execute_glmm_regression( Returns ------- - pd.DataFrame - Model results. + pandas.DataFrame + The model results. """ # noqa : E501 # Builds the formula elr_formula_str = elr_outcome + " ~ " + " + ".join(elr_predictors) @@ -2279,19 +2280,19 @@ def elr_parse_variable_name(var_name): def execute_glm_regression( - elr_dataframe_df: pd.DataFrame, + elr_dataframe_df: pandas.DataFrame, elr_outcome: str, elr_predictors: typing.Iterable, model_type: str = "linear", print_results: bool = True, labels: dict[str, str] | None = None, reg_type: str = "Multi", -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Executes a GLM (Generalized Linear Model) for linear or logistic regression. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Executes a GLM (Generalized Linear Model) for linear or logistic regression. Parameters ---------- - elr_dataframe_df : pd.DataFrame + elr_dataframe_df : pandas.DataFrame The incoming data. elr_outcome : str @@ -2317,8 +2318,10 @@ def execute_glm_regression( Optional regression type - ``"uni"`` for univariate, ``"multi"`` for multivariate. Defaults to ``"multi"``. - Returns: - - summary_df: DataFrame with the model results. + Returns + -------- + pandas.DataFrame + The model results. """ # noqa : E501 # Defines the family according to model_type if model_type.lower() == "logistic": @@ -2464,17 +2467,17 @@ def parse_variable_name(var_name): def execute_cox_model( - data: pd.DataFrame, + data: pandas.DataFrame, duration_col: str, event_col: str, predictors: typing.Iterable[str], labels: dict[str, str] | None = None, -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Executes a Cox Proportional Hazards model without weights and returns a summary of the results. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Executes a Cox Proportional Hazards model without weights and returns a summary of the results. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. duration_col : str @@ -2491,8 +2494,8 @@ def execute_cox_model( Returns ------- - pd.DataFrame - Results of the Cox model. + pandas.DataFrame + The model results. """ # noqa : E501 # Ensure categorical variables are treated appropriately categorical_vars = data.select_dtypes( @@ -2548,18 +2551,18 @@ def execute_cox_model( def execute_kaplan_meier( - data: pd.DataFrame, + data: pandas.DataFrame, duration_col: str, event_col: str, group_col: str, alpha=0.05, n_times=5, -) -> tuple[pd.DataFrame, pd.DataFrame, float]: +) -> tuple[pandas.DataFrame, pandas.DataFrame, float]: """:py:class:`tuple` : Executes the Kaplan-Meier model and returns the results. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. duration_col : str @@ -2579,7 +2582,7 @@ def execute_kaplan_meier( Returns ------- - pd.DataFrame + pandas.DataFrame A tuple consisting of the model results, risk table and the :math:`p`-value. """ # noqa : E501 @@ -2659,27 +2662,27 @@ def execute_kaplan_meier( def impute_miss_val( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, outcome_column: str = "outco_binary_outcome", missing_threshold: float = 0.7, verbose: bool = False, -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : The data with missing values imputed. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : The data with missing values imputed. Imputes missing values or drops columns based on missing value proportion and median. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. outcome_column : str, default="outco_binary_outcome" - Optional outcome column, default=``"outco_binary_outcome"``. + Optional outcome column, defaults to ``"outco_binary_outcome"``. missing_threshold : float, default=0.7 A proportional imputation threshold for missing values, defaults to @@ -2691,7 +2694,7 @@ def impute_miss_val( Returns ------- - pd.DataFrame + pandas.DataFrame Data with missing values imputed or columns dropped. """ # noqa : E501 keep_columns = ["subjid", outcome_column] @@ -2734,24 +2737,24 @@ def impute_miss_val( def rmv_low_var( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, mad_threshold: float = 0.1, freq_threshold: float = 0.05, outcome_column: str = "outco_binary_outcome", verbose: bool = False, -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Removes numerical variables from the data with Median Absolute Deviation (MAD) below a given threshold. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Removes numerical variables from the data with Median Absolute Deviation (MAD) below a given threshold. Excludes binary columns from MAD calculation. Removes binary columns with very low frequencies. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. mad_threshold : float, default=0.1 @@ -2768,7 +2771,7 @@ def rmv_low_var( Returns ------- - pd.DataFrame + pandas.DataFrame The data with low MAD columns removed. """ # noqa : E501 keep_columns = ["subjid", outcome_column] @@ -2827,23 +2830,23 @@ def rmv_low_var( def rmv_high_corr( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, outcome_column: str = "outco_binary_outcome", correlation_threshold: float = 0.5, verbose: bool = False, -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Removes variables in the data with high multicollinearity. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Removes variables in the data with high multicollinearity. Arbitrarily selecting one variable to remove if the correlation between two variables is above a threshold. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. outcome_column : str, default=``"outco_binary_outcome"`` @@ -2857,7 +2860,7 @@ def rmv_high_corr( Returns ------- - pd.DataFrame + pandas.DataFrame The data with high correlation variables removed. """ # noqa : E501 keep_columns = ["subjid", outcome_column] @@ -2895,7 +2898,7 @@ def rmv_high_corr( def lasso_var_sel_binary( - data: pd.DataFrame, + data: pandas.DataFrame, outcome_column: str = "mapped_outcome", metric: str = "balanced_accuracy", threshold: float = 1e-3, @@ -2913,7 +2916,7 @@ def lasso_var_sel_binary( Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. outcome_column : str, default="mapped_outcome" @@ -2925,10 +2928,7 @@ def lasso_var_sel_binary( threshold : float, default=1e-3 Optional threshold, defaults to :math:`0.001`. - gridsearch_params : dict, default={ - "l1_ratios": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], - "Cs": [1e-3, 3.16e-3, 1e-2, 3.16e-2, 1e-1, 3.16e-1, 1, 3.16, 10] - } + gridsearch_params : dict, default={"l1_ratios": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], "Cs": [1e-3, 3.16e-3, 1e-2, 3.16e-2, 1e-1, 3.16e-1, 1, 3.16, 10]} Optional grid search params, defaults to: :: @@ -3283,7 +3283,7 @@ def create_grouped_results( def get_parameter_ranking( logistic: typing.Any, n_top: int = 10, threshold: float = 1e-3 -) -> pd.DataFrame: +) -> pandas.DataFrame: """:py:class:pd.DataFrame : Returns a dataframe of rankings of parameter combinations using stored scores and coefficient paths. Parameters @@ -3299,7 +3299,7 @@ def get_parameter_ranking( Returns ------- - pd.DataFrame + pandas.DataFrame The dataframe of parameter rankings. """ # noqa : E501 # Create empty list to store parameter information diff --git a/isaricanalytics/redcap_data.py b/isaricanalytics/redcap_data.py index 7d9fc78..53eb247 100644 --- a/isaricanalytics/redcap_data.py +++ b/isaricanalytics/redcap_data.py @@ -49,13 +49,15 @@ # -- 3rd party libraries -- import numpy as np -import pandas as pd +import pandas import requests # -- Internal libraries -- from isaricanalytics.logging.logger import setup_logger logger = setup_logger(__name__) +pd = pandas # An alias to allow Pandas code refs to work independently +# of Pandas Intersphinx refs in type hinting and docstrings ############################################ @@ -95,8 +97,8 @@ def get_records( redcap_api_key: str, data_access_groups: typing.Iterable[str] | None = None, user_assigned_to_dag: bool = False, -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns a dataframe of records from the REDCap API. +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns a dataframe of records from the REDCap API. Parameters ---------- @@ -114,9 +116,9 @@ def get_records( Returns ------- - pd.DataFrame + pandas.DataFrame Records from the REDCap API data. - """ + """ # noqa : E501 started = time.perf_counter() if (data_access_groups is None) or (user_assigned_to_dag is False): @@ -214,8 +216,8 @@ def get_records( return data -def get_data_dictionary(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns a data dictionary from the REDCap API. +def get_data_dictionary(redcap_url: str, redcap_api_key: str) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns a data dictionary from the REDCap API. Parameters ---------- @@ -227,7 +229,7 @@ def get_data_dictionary(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: Returns ------- - pd.DataFrame + pandas.DataFrame Data dictionary from the REDCap API. """ conex = { @@ -242,8 +244,8 @@ def get_data_dictionary(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: return pd.read_csv(io.StringIO(response.text), keep_default_na=False) -def get_events_and_forms_info(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns a combined dataframe of events, forms and their mapppings from the REDCap API. +def get_events_and_forms_info(redcap_url: str, redcap_api_key: str) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns a combined dataframe of events, forms and their mapppings from the REDCap API. Parameters ---------- @@ -255,7 +257,7 @@ def get_events_and_forms_info(redcap_url: str, redcap_api_key: str) -> pd.DataFr Returns ------- - pd.DataFrame + pandas.DataFrame Events, forms and their mapppings from the REDCap API. """ # noqa: E501 conex = { @@ -321,8 +323,8 @@ def get_events_and_forms_info(redcap_url: str, redcap_api_key: str) -> pd.DataFr return form, form_event -def get_form_event(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns a combined dataframe of events, forms and their mapppings from the REDCap API. +def get_form_event(redcap_url: str, redcap_api_key: str) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns a combined dataframe of events, forms and their mapppings from the REDCap API. .. warning:: @@ -338,7 +340,7 @@ def get_form_event(redcap_url: str, redcap_api_key: str) -> pd.DataFrame: Returns ------- - pd.DataFrame + pandas.DataFrame Events, forms and their mapppings from the REDCap API. """ # noqa: E501 warnings.warn( @@ -490,19 +492,19 @@ def get_label(x: typing.Iterable[str]) -> list[str]: return get_labels(x) -def add_answer_dict(dictionary: pd.DataFrame) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns the REDCap schema data dictionary with a lookup dict of labels and values. +def add_answer_dict(dictionary: pandas.DataFrame) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns the REDCap schema data dictionary with a lookup dict of labels and values. By default, ignores Yes/No/Unknown radio variables. Parameters ---------- - dictionary : pd.DataFrame + dictionary : pandas.DataFrame REDCap schema data dictionary. Returns ------- - pd.DataFrame + pandas.DataFrame An updated REDCap schema data dictionary with a lookup dict of labels and values. """ # noqa: E501 @@ -530,7 +532,7 @@ def add_answer_dict(dictionary: pd.DataFrame) -> pd.DataFrame: def list_categorical_onehot_columns( - dictionary_row: dict[str, typing.Any], data: pd.DataFrame, sep: str = "___" + dictionary_row: dict[str, typing.Any], data: pandas.DataFrame, sep: str = "___" ) -> list[str]: """:py:class:`list` Returns a list of categorical onehot-encoded columns in the given dataframe. @@ -539,7 +541,7 @@ def list_categorical_onehot_columns( dictionary_row : dict A row of the data dictionary. - data : pd.DataFrame + data : pandas.DataFrame The incoming data. sep : str, default="___" @@ -557,7 +559,7 @@ def list_categorical_onehot_columns( def list_checkbox_onehot_columns( - dictionary_row: dict[str, typing.Any], data: pd.DataFrame, sep: str = "___" + dictionary_row: dict[str, typing.Any], data: pandas.DataFrame, sep: str = "___" ) -> list[str]: """:py:class:`list` Returns a list of checkbox onehot-encoded columns in the given dataframe. @@ -566,7 +568,7 @@ def list_checkbox_onehot_columns( dictionary_row : dict A row of the data dictionary. - data : pd.DataFrame + data : pandas.DataFrame The incoming data. sep : str, default="___" @@ -601,9 +603,9 @@ def get_section_prefix(x: str) -> str: def add_onehot_variables( - data: pd.DataFrame, dictionary: pd.DataFrame, sep: str = "___" -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Returns the data dictionary with rows for onehot-encoded categorical variables. + data: pandas.DataFrame, dictionary: pandas.DataFrame, sep: str = "___" +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Returns the data dictionary with rows for onehot-encoded categorical variables. Add new rows to the dictionary for onehot-encoded categorical variables, using only the answers that exist within the data, e.g. if checkbox columns @@ -612,10 +614,10 @@ def add_onehot_variables( Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. sep : str, default="___" @@ -623,7 +625,7 @@ def add_onehot_variables( Returns ------- - pd.DataFrame + pandas.DataFrame The data dictionary with rows for onehot-encoded categorical variables. """ # noqa: E501 new_dictionary = dictionary.copy() @@ -749,17 +751,17 @@ def is_yesno(x: str) -> str: return is_yesno_question(x) -def convert_dictionary_field_type(dictionary: pd.DataFrame) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Return a dictionary of variable types, based on REDCAP structure. +def convert_dictionary_field_type(dictionary: pandas.DataFrame) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Return a dictionary of variable types, based on REDCAP structure. Parameters ---------- - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The REDCap data dictionary. Returns ------- - pd.DataFrame + pandas.DataFrame a dictionary of variable types, based on REDCAP structure. """ # noqa : E501 new_dictionary = dictionary.copy() @@ -795,13 +797,13 @@ def convert_dictionary_field_type(dictionary: pd.DataFrame) -> pd.DataFrame: def replace_with_nan_for_missing_code_checkbox( - data: pd.DataFrame, missing_data_codes: dict[str, typing.Any] -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Return the input dataframe with missing code checkbox values converted to NaN. + data: pandas.DataFrame, missing_data_codes: dict[str, typing.Any] +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Return the input dataframe with missing code checkbox values converted to NaN. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. missing_data_codes : dict @@ -809,7 +811,7 @@ def replace_with_nan_for_missing_code_checkbox( Returns ------- - pd.DataFrame + pandas.DataFrame The input dataframe with missing code checkbox values converted to NaN. """ # noqa : E501 missing_data_values = [x.lower() for x in missing_data_codes.values()] @@ -853,8 +855,8 @@ def is_unlisted_item(x: typing.Iterable[str]) -> str: def combine_unlisted_variables( - data: pd.DataFrame, dictionary: pd.DataFrame, sep: str = "___" -) -> tuple[pd.DataFrame]: + data: pandas.DataFrame, dictionary: pandas.DataFrame, sep: str = "___" +) -> tuple[pandas.DataFrame]: """:py:class:`tuple` : Combine variables in repetitions of a question. Combine variables that exist in repeated versions of the same question @@ -863,10 +865,10 @@ def combine_unlisted_variables( Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The REDCap data dictionary. sep : str, default="___" @@ -926,24 +928,24 @@ def combine_unlisted_variables( def rename_checkbox_variables( - data: pd.DataFrame, dictionary: pd.DataFrame -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Rename checkbox variable columns. + data: pandas.DataFrame, dictionary: pandas.DataFrame +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Rename checkbox variable columns. By default the suffix is their answer option value. Convert this answer option value to the answer option name. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The REDCap data dictionary. Returns ------- - pd.DataFrame + pandas.DataFrame The updated data. """ checkbox_ind = dictionary["field_type"] == "checkbox" @@ -985,7 +987,7 @@ def get_branching_logic_variables(branching_logic: str) -> list[str]: def resolve_checkbox_branching_logic( data: pd.DataFrame, dictionary: pd.DataFrame ) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Resolves checkbox logic. + """:py:class:`pandas.DataFrame` : Resolves checkbox logic. By default, a cell is marked as 'Unchecked' in the absence of the positive, even if the question was not asked to the subjid. If the question @@ -995,15 +997,15 @@ def resolve_checkbox_branching_logic( Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The REDCap data dictionary. Returns ------- - pd.DataFrame + pandas.DataFrame The data with the checkbox branching logic resolved. """ checkbox_ind = dictionary.loc[(dictionary["field_type"] == "checkbox")] @@ -1027,10 +1029,10 @@ def resolve_checkbox_branching_logic( def harmonise_age( - data: pd.DataFrame, + data: pandas.DataFrame, age_columns: typing.Iterable[str] = ["demog_age", "demog_age_units"], ) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : The data with ages harmonised. + """:py:class:`pandas.DataFrame` : The data with ages harmonised. .. warning:: @@ -1039,7 +1041,7 @@ def harmonise_age( Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. age_columns : typing.Iterable, default=["demog_age", "demog_age_units"] @@ -1047,7 +1049,7 @@ def harmonise_age( Returns ------- - pd.DataFrame + pandas.DataFrame The data with ages harmonised. """ warnings.warn( @@ -1073,18 +1075,18 @@ def harmonise_age( def map_variable( - variable: pd.Series, + variable: pandas.Series, mapping_dict: dict[str, typing.Any], non_nan_value: str = "Other / Unknown", -) -> pd.Series: - """:py:class:`pd.Series` : Map a variable column using a dict. +) -> pandas.Series: + """:py:class:`pandas.Series` : Map a variable column using a dict. Any non-NaN value not in the dict keys is converted to the value specified by ``other_value_str``. Parameters ---------- - variable : pd.Series + variable : pandas.Series The variable column to map. mapping_dict : dict @@ -1101,12 +1103,12 @@ def map_variable( return variable -def load_units_conversion_table() -> pd.DataFrame: +def load_units_conversion_table() -> pandas.DataFrame: """:py:class:`pandas.DataFrame` : Loads the conversion table from a CSV. Returns ------- - pd.DataFrame + pandas.DataFrame The conversion table. """ try: @@ -1122,7 +1124,7 @@ def load_units_conversion_table() -> pd.DataFrame: ) -def load_countries_table(encoding: str = "latin-1") -> pd.DataFrame: +def load_countries_table(encoding: str = "latin-1") -> pandas.DataFrame: """:py:class:`pandas.DataFrame` : Loads countries from a CSV. Parameters @@ -1132,7 +1134,7 @@ def load_countries_table(encoding: str = "latin-1") -> pd.DataFrame: Returns ------- - pd.DataFrame + pandas.DataFrame The countries table. """ try: @@ -1152,21 +1154,21 @@ def load_countries_table(encoding: str = "latin-1") -> pd.DataFrame: def homogenise_variables( - data: pd.DataFrame, dictionary: pd.DataFrame + data: pandas.DataFrame, dictionary: pandas.DataFrame ) -> tuple[pd.DataFrame]: - """:py:class:`pd.DataFrame` : Converts variables in given units in the data based on a conversion table. + """:py:class:`pandas.DataFrame` : Converts variables in given units in the data based on a conversion table. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame Conversion table/dictionary, as a Pandas dataframe. Returns ------- - pd.DataFrame + pandas.DataFrame The data with unit conversions applied. """ # noqa : E501 conversion_table = load_units_conversion_table() @@ -1233,24 +1235,24 @@ def homogenise_variables( def convert_onehot_to_binary( - data: pd.DataFrame, dictionary: pd.DataFrame -) -> pd.DataFrame: - """:py:class:`pd.DataFrame` : Converts onehot-encoded columns in the data. + data: pandas.DataFrame, dictionary: pandas.DataFrame +) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : Converts onehot-encoded columns in the data. The conversions will be True/False/NaN values, and answers from the data dictionary discarded if they exist. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The REDCap data dictionary. Returns ------- - pd.DataFrame + pandas.DataFrame The data with the one-hot columns appropriately converted. """ binary_ind = dictionary["field_type"] == "binary" @@ -1275,18 +1277,18 @@ def convert_onehot_to_binary( def initial_data_processing( - data: pd.DataFrame, - dictionary: pd.DataFrame, + data: pandas.DataFrame, + dictionary: pandas.DataFrame, missing_data_codes: dict[str, typing.Any], -) -> tuple[pd.DataFrame]: +) -> tuple[pandas.DataFrame]: """:py:class:`tuple` : Initial processing function invoked after the REDCap API call. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming REDCap data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The REDCap data dictionary. missing_data_codes : dict @@ -1388,16 +1390,16 @@ def initial_data_processing( def get_df_map( - data: pd.DataFrame, dictionary: pd.DataFrame -) -> tuple[pd.DataFrame | dict[str, typing.Any]]: - """:py:class:`pd.DataFrame` : Returns a dataframe with single-event rows converted to a format with one row per patient. + data: pandas.DataFrame, dictionary: pandas.DataFrame +) -> tuple[pandas.DataFrame | dict[str, typing.Any]]: + """:py:class:`pandas.DataFrame` : Returns a dataframe with single-event rows converted to a format with one row per patient. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming REDCap data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The REDCap data. Returns @@ -1468,16 +1470,16 @@ def get_df_map( def get_df_forms( - data: pd.DataFrame, dictionary: pd.DataFrame -) -> dict[str, pd.DataFrame]: + data: pandas.DataFrame, dictionary: pandas.DataFrame +) -> dict[str, pandas.DataFrame]: """:py:class:`dict` : Returns a dict of clinical form names and associated dataframes. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame The incoming REDCap data. - dictionary : pd.DataFrame + dictionary : pandas.DataFrame The data dictionary. Returns @@ -1505,7 +1507,7 @@ def get_redcap_data( data_access_groups: typing.Iterable[str] | None = None, user_assigned_to_dag: bool | None = False, country_mapping: dict | None = None, -) -> tuple[pd.DataFrame | dict[str, pd.DataFrame] | dict[str, typing.Any]]: +) -> tuple[pandas.DataFrame | dict[str, pandas.DataFrame] | dict[str, typing.Any]]: """:py:class:`tuple` : Returns data from REDCap API and transforms them into analysis-ready dataframes. Parameters diff --git a/isaricanalytics/utils.py b/isaricanalytics/utils.py index 1e20a7e..299a1f4 100644 --- a/isaricanalytics/utils.py +++ b/isaricanalytics/utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + __all__ = [ "clean_figure_table", "strip_html", @@ -11,7 +13,7 @@ import typing # -- 3rd party libraries -- -import pandas as pd +import pandas # -- Internal libraries -- @@ -62,8 +64,8 @@ def strip_nonstandard_unicode_chars(value: typing.Any) -> str | typing.Any: return value -def clean_figure_table(figure_table: pd.DataFrame) -> pd.DataFrame: - """:py:class:pandas.DataFrame : A cleaned figure table dataframe. +def clean_figure_table(figure_table: pandas.DataFrame) -> pandas.DataFrame: + """:py:class:`pandas.DataFrame` : A cleaned figure table dataframe. The cleaning steps are unique to the Plotly graph object table format from which the table CSVs were originally, which contain HTML styling elements diff --git a/isaricanalytics/visualisation.py b/isaricanalytics/visualisation.py index 241dff8..7635257 100644 --- a/isaricanalytics/visualisation.py +++ b/isaricanalytics/visualisation.py @@ -31,13 +31,18 @@ # -- 3rd party libraries -- import numpy as np -import pandas as pd +import pandas +import plotly import plotly.express as px import plotly.graph_objs as go from plotly.subplots import make_subplots # -- Internal libraries -- + +pd = pandas # An alias to allow Pandas code refs to work independently +# of Pandas Intersphinx refs in type hinting and docstrings + ############################################ ############################################ # Figures @@ -46,17 +51,17 @@ def fig_placeholder( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Placeholder scatter plot", xlabel: str = "", ylabel: str = "", height: int = 450, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a placeholder scatter plot. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a placeholder scatter plot. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Placeholder scatter plot" @@ -73,8 +78,8 @@ def fig_placeholder( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ if data is None: x = [1, 2, 3, 4, 5] @@ -102,7 +107,7 @@ def fig_placeholder( def fig_pie( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Pie chart", xlabel: str = "", ylabel: str = "", @@ -111,11 +116,11 @@ def fig_pie( values: str | int | pd.Series | typing.Iterable = "", height: int = 450, ): - """:py:class:`go.Figure` : Returns a pie chart figure. + """:py:class:`plotly.graph_objs.Figure` : Returns a pie chart figure. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Placeholder scatter plot" @@ -141,8 +146,8 @@ def fig_pie( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -167,7 +172,7 @@ def fig_pie( def fig_timelines( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Timeline", label_col: str = "", group_col: str = "", @@ -177,12 +182,12 @@ def fig_timelines( min_width: int = 2, max_width: int = 10, height: int = 500, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a timeline figure. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a timeline figure. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Timeline" @@ -214,8 +219,8 @@ def fig_timelines( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() df[start_date] = pd.to_datetime(df[start_date]) @@ -291,18 +296,18 @@ def fig_timelines( def fig_sunburst( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Sunburst Chart", path: list[str | int] | pd.Series | typing.Iterable | None = ["level0", "level1"], values: str | int | pd.Series | typing.Iterable = "values", base_color_map: dict[str, str] | None = None, height: int = 430, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a sunburst plot. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a sunburst plot. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Sunburst Chart" @@ -323,8 +328,8 @@ def fig_sunburst( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -352,7 +357,7 @@ def fig_sunburst( def fig_bar_chart( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Bar Chart", xlabel: str = "", ylabel: str = "", @@ -361,12 +366,12 @@ def fig_bar_chart( xaxis_tickformat: str = "%m-%Y", base_color_map: dict[str, str] | None = None, height: int = 340, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a bar chart. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a bar chart. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Bar Chart" @@ -397,8 +402,8 @@ def fig_bar_chart( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -459,8 +464,8 @@ def fig_upset( data: tuple[pd.DataFrame], title: str = "Upset Plot", height: int = 480, -) -> go.Figure: - """:py:class:`go.Figure` : Returns an upset plot. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns an upset plot. Parameters ---------- @@ -476,8 +481,8 @@ def fig_upset( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ counts = data[0].copy() intersections = data[1].copy() @@ -641,18 +646,18 @@ def fig_upset( def fig_count_chart( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Count Chart", xlabel: str = "Count", ylabel: str = "Variable", base_color_map: dict[str, str] | None = None, height: int = 350, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a count chart. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a count chart. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Count Chart" @@ -672,8 +677,8 @@ def fig_count_chart( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() column_names = ["label", "count", "short_label"] @@ -743,18 +748,18 @@ def fig_count_chart( def fig_frequency_chart( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Frequency Chart", xlabel: str = "Proportion", ylabel: str = "Variable", base_color_map: dict[str, str] | None = None, height: int = 350, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a frequency chart. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a frequency chart. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Frequency Chart" @@ -774,8 +779,8 @@ def fig_frequency_chart( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -869,16 +874,16 @@ def fig_frequency_chart( def fig_table( - data: pd.DataFrame, + data: pandas.DataFrame, table_key: str = "", columnwidth: typing.Iterable[int | float] | None = None, height: int = 500, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a table figure. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a table figure. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. table_key : str, default="" @@ -892,8 +897,8 @@ def fig_table( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -940,18 +945,18 @@ def fig_table( def fig_dual_stack_pyramid( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Dual-Sided Stacked Pyramid Chart", xlabel: str = "Count", ylabel: str = "Category", base_color_map: dict[str, str] | None = None, height: int = 430, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a dual-sided stacked pyramid chart. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a dual-sided stacked pyramid chart. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Dual-Sided Stacked Pyramid Chart" @@ -971,9 +976,9 @@ def fig_dual_stack_pyramid( Returns ------- - go.Figure - The figure. - """ + plotly.graph_objs.Figure + The Plotly figure. + """ # noqa : E501 df = data.copy() # Error Handling @@ -1114,14 +1119,14 @@ def fig_dual_stack_pyramid( def fig_flowchart( - data: pd.DataFrame, + data: pandas.DataFrame, height: int = 430, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a flowchart. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a flowchart. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. height : int, default=430 @@ -1129,8 +1134,8 @@ def fig_flowchart( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -1196,7 +1201,7 @@ def fig_flowchart( def fig_forest_plot( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Forest Plot", xlabel: str = "Odds Ratio (95% CI)", ylabel: str = "", @@ -1205,12 +1210,12 @@ def fig_forest_plot( marker: dict[str, typing.Any] | None = None, noeffect_line: bool = True, height: int = 600, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a forest plot. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a forest plot. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Forest Plot" @@ -1239,8 +1244,8 @@ def fig_forest_plot( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -1326,14 +1331,14 @@ def fig_forest_plot( def fig_text( - data: pd.DataFrame, + data: pandas.DataFrame, height: int = 430, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a figure with an annotation. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a figure with an annotation. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. height : int, default=430 @@ -1341,8 +1346,8 @@ def fig_text( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ fig = go.Figure() @@ -1373,8 +1378,8 @@ def fig_kaplan_meier( xlim: typing.Iterable[float | int] | None = None, p_value: float | None = None, height: int = 480, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a Kaplan-Meier plot. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a Kaplan-Meier plot. Parameters ---------- @@ -1411,8 +1416,8 @@ def fig_kaplan_meier( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df_km = data[0].copy() risk_table = data[1].copy() @@ -1619,7 +1624,7 @@ def fig_kaplan_meier( def fig_line_chart( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Line chart", xlabel: str = "", ylabel: str = "", @@ -1629,12 +1634,12 @@ def fig_line_chart( lower_column: str | None = None, upper_column: str | None = None, line_color: str | None = None, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a line chart. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a line chart. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Line chart" @@ -1666,8 +1671,8 @@ def fig_line_chart( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -1727,7 +1732,7 @@ def fig_line_chart( def fig_bar_line_chart( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "Combined bar line chart", xlabel: str = "", ylabel_left: str = "", @@ -1740,12 +1745,12 @@ def fig_bar_line_chart( bar_color: str | None = None, line_color: str | None = None, height: int = 500, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a bar-line chart. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a bar-line chart. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="Combined bar line chart" @@ -1783,8 +1788,8 @@ def fig_bar_line_chart( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ df = data.copy() @@ -1866,7 +1871,7 @@ def fig_bar_line_chart( def fig_heatmaps( - data: pd.DataFrame, + data: pandas.DataFrame, title: str = "", subplot_titles: list[str] | None = None, ylabel: str = "", @@ -1878,12 +1883,12 @@ def fig_heatmaps( include_annotations: bool = False, base_color_map: dict[str, str] | None = None, height: int = 750, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a heatmaps chart. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a heatmaps chart. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. title : str, default="" @@ -1921,8 +1926,8 @@ def fig_heatmaps( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ if isinstance(data, tuple) is False: data = (data,) @@ -1996,14 +2001,14 @@ def fig_heatmaps( def fig_sankey( - data: pd.DataFrame, + data: pandas.DataFrame, height: int = 500, -) -> go.Figure: - """:py:class:`go.Figure` : Returns a Sankey plot. +) -> plotly.graph_objs.Figure: + """:py:class:`plotly.graph_objs.Figure` : Returns a Sankey plot. Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame Incoming data. height : int, default=500 @@ -2011,8 +2016,8 @@ def fig_sankey( Returns ------- - go.Figure - The figure. + plotly.graph_objs.Figure + The Plotly figure. """ node = data[0].copy() link = data[1].copy() From 802c75398a96e5258e0aa10f6676618cbfed6ffa Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 12:07:34 +0100 Subject: [PATCH 28/34] ci: remove workflow chaining due to lack of full GitHub support on PRs --- .github/workflows/build.yml | 8 +++----- .github/workflows/test.yml | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be82871..bec0041 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,10 +1,6 @@ name: build on: - workflow_run: - workflows: Tests and Coverage - types: - - completed push: branches: main pull_request: @@ -12,10 +8,12 @@ on: jobs: build: runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'success' }} timeout-minutes: 30 steps: + - run: | + echo "github.event_name=${{ github.event_name }}" + echo "github.event.workflow_run.conclusion=${{ github.event.workflow_run.conclusion }}" - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 248648f..22c60b2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,10 +1,6 @@ name: Tests and Coverage on: - workflow_run: - workflows: pre-commit - types: - - completed push: branches: - main @@ -13,10 +9,12 @@ on: jobs: unit-test: runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'success' }} timeout-minutes: 30 steps: + - run: | + echo "github.event_name=${{ github.event_name }}" + echo "github.event.workflow_run.conclusion=${{ github.event.workflow_run.conclusion }}" - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd From 25dd0193471100b4ab9ba9573fc7017a53d0242d Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 12:08:32 +0100 Subject: [PATCH 29/34] chore: remove pylock TOML --- pylock.toml | 3269 --------------------------------------------------- 1 file changed, 3269 deletions(-) delete mode 100644 pylock.toml diff --git a/pylock.toml b/pylock.toml deleted file mode 100644 index d2f0f1d..0000000 --- a/pylock.toml +++ /dev/null @@ -1,3269 +0,0 @@ -lock-version = "1.0" -requires-python = ">=3.11" -environments = [ - "python_version >= \"3.11\"", -] -extras = ["docs", "pre-commit", "test"] -dependency-groups = ["default"] -default-groups = ["default"] -created-by = "pdm" -[[packages]] -name = "accessible-pygments" -version = "0.0.5" -requires-python = ">=3.9" -sdist = {name = "accessible_pygments-0.0.5.tar.gz", url = "https://files.pythonhosted.org/packages/bc/c1/bbac6a50d02774f91572938964c582fff4270eee73ab822a4aeea4d8b11b/accessible_pygments-0.0.5.tar.gz", hashes = {sha256 = "40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872"}} -wheels = [ - {name = "accessible_pygments-0.0.5-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/8d/3f/95338030883d8c8b91223b4e21744b04d11b161a3ef117295d8241f50ab4/accessible_pygments-0.0.5-py3-none-any.whl",hashes = {sha256 = "88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "pygments>=1.5", -] - -[[packages]] -name = "alabaster" -version = "1.0.0" -requires-python = ">=3.10" -sdist = {name = "alabaster-1.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hashes = {sha256 = "c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}} -wheels = [ - {name = "alabaster-1.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl",hashes = {sha256 = "fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "anyio" -version = "4.13.0" -requires-python = ">=3.10" -sdist = {name = "anyio-4.13.0.tar.gz", url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hashes = {sha256 = "334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}} -wheels = [ - {name = "anyio-4.13.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl",hashes = {sha256 = "08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "exceptiongroup>=1.0.2; python_version < \"3.11\"", - "idna>=2.8", - "typing-extensions>=4.5; python_version < \"3.13\"", -] - -[[packages]] -name = "appnope" -version = "0.1.4" -requires-python = ">=3.6" -sdist = {name = "appnope-0.1.4.tar.gz", url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hashes = {sha256 = "1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}} -wheels = [ - {name = "appnope-0.1.4-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl",hashes = {sha256 = "502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}}, -] -marker = "platform_system == \"Darwin\" and \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "astroid" -version = "4.0.4" -requires-python = ">=3.10.0" -sdist = {name = "astroid-4.0.4.tar.gz", url = "https://files.pythonhosted.org/packages/07/63/0adf26577da5eff6eb7a177876c1cfa213856be9926a000f65c4add9692b/astroid-4.0.4.tar.gz", hashes = {sha256 = "986fed8bcf79fb82c78b18a53352a0b287a73817d6dbcfba3162da36667c49a0"}} -wheels = [ - {name = "astroid-4.0.4-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b0/cf/1c5f42b110e57bc5502eb80dbc3b03d256926062519224835ef08134f1f9/astroid-4.0.4-py3-none-any.whl",hashes = {sha256 = "52f39653876c7dec3e3afd4c2696920e05c83832b9737afc21928f2d2eb7a753"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "typing-extensions>=4; python_version < \"3.11\"", -] - -[[packages]] -name = "asttokens" -version = "3.0.1" -requires-python = ">=3.8" -sdist = {name = "asttokens-3.0.1.tar.gz", url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hashes = {sha256 = "71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7"}} -wheels = [ - {name = "asttokens-3.0.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl",hashes = {sha256 = "15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "attrs" -version = "26.1.0" -requires-python = ">=3.9" -sdist = {name = "attrs-26.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hashes = {sha256 = "d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}} -wheels = [ - {name = "attrs-26.1.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl",hashes = {sha256 = "c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "autograd" -version = "1.8.0" -requires-python = ">=3.9" -sdist = {name = "autograd-1.8.0.tar.gz", url = "https://files.pythonhosted.org/packages/67/1c/3c24ec03c8ba4decc742b1df5a10c52f98c84ca8797757f313e7bdcdf276/autograd-1.8.0.tar.gz", hashes = {sha256 = "107374ded5b09fc8643ac925348c0369e7b0e73bbed9565ffd61b8fd04425683"}} -wheels = [ - {name = "autograd-1.8.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/84/ea/e16f0c423f7d83cf8b79cae9452040fb7b2e020c7439a167ee7c317de448/autograd-1.8.0-py3-none-any.whl",hashes = {sha256 = "4ab9084294f814cf56c280adbe19612546a35574d67c574b04933c7d2ecb7d78"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "numpy<3", -] - -[[packages]] -name = "autograd-gamma" -version = "0.5.0" -sdist = {name = "autograd-gamma-0.5.0.tar.gz", url = "https://files.pythonhosted.org/packages/85/ae/7f2031ea76140444b2453fa139041e5afd4a09fc5300cfefeb1103291f80/autograd-gamma-0.5.0.tar.gz", hashes = {sha256 = "f27abb7b8bb9cffc8badcbf59f3fe44a9db39e124ecacf1992b6d952934ac9c4"}} -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "autograd>=1.2.0", - "scipy>=1.2.0", -] - -[[packages]] -name = "babel" -version = "2.18.0" -requires-python = ">=3.8" -sdist = {name = "babel-2.18.0.tar.gz", url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hashes = {sha256 = "b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d"}} -wheels = [ - {name = "babel-2.18.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl",hashes = {sha256 = "e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "pytz>=2015.7; python_version < \"3.9\"", -] - -[[packages]] -name = "beautifulsoup4" -version = "4.14.3" -requires-python = ">=3.7.0" -sdist = {name = "beautifulsoup4-4.14.3.tar.gz", url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hashes = {sha256 = "6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86"}} -wheels = [ - {name = "beautifulsoup4-4.14.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl",hashes = {sha256 = "0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "soupsieve>=1.6.1", - "typing-extensions>=4.0.0", -] - -[[packages]] -name = "bleach" -version = "6.3.0" -requires-python = ">=3.10" -sdist = {name = "bleach-6.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hashes = {sha256 = "6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22"}} -wheels = [ - {name = "bleach-6.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl",hashes = {sha256 = "fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "webencodings", -] - -[[packages]] -name = "certifi" -version = "2026.2.25" -requires-python = ">=3.7" -sdist = {name = "certifi-2026.2.25.tar.gz", url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hashes = {sha256 = "e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}} -wheels = [ - {name = "certifi-2026.2.25-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl",hashes = {sha256 = "027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "cffi" -version = "2.0.0" -requires-python = ">=3.9" -sdist = {name = "cffi-2.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hashes = {sha256 = "44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}} -wheels = [ - {name = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}}, - {name = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}}, - {name = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}}, - {name = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}}, - {name = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}}, - {name = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}}, - {name = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}}, - {name = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}}, - {name = "cffi-2.0.0-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl",hashes = {sha256 = "087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}}, - {name = "cffi-2.0.0-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl",hashes = {sha256 = "203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}}, - {name = "cffi-2.0.0-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl",hashes = {sha256 = "dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}}, - {name = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}}, - {name = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}}, - {name = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}}, - {name = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}}, - {name = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}}, - {name = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}}, - {name = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}}, - {name = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}}, - {name = "cffi-2.0.0-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl",hashes = {sha256 = "1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}}, - {name = "cffi-2.0.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}}, - {name = "cffi-2.0.0-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}}, - {name = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}}, - {name = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}}, - {name = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}}, - {name = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}}, - {name = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}}, - {name = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}}, - {name = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}}, - {name = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}}, - {name = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}}, - {name = "cffi-2.0.0-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl",hashes = {sha256 = "74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}}, - {name = "cffi-2.0.0-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl",hashes = {sha256 = "19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}}, - {name = "cffi-2.0.0-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl",hashes = {sha256 = "256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}}, - {name = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}}, - {name = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}}, - {name = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}}, - {name = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}}, - {name = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}}, - {name = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}}, - {name = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}}, - {name = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}}, - {name = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}}, - {name = "cffi-2.0.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl",hashes = {sha256 = "da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}}, - {name = "cffi-2.0.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}}, - {name = "cffi-2.0.0-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl",hashes = {sha256 = "4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}}, - {name = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl",hashes = {sha256 = "b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}}, - {name = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}}, - {name = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}}, - {name = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}}, - {name = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}}, - {name = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}}, - {name = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}}, - {name = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}}, - {name = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}}, - {name = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}}, - {name = "cffi-2.0.0-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl",hashes = {sha256 = "c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}}, - {name = "cffi-2.0.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}}, - {name = "cffi-2.0.0-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl",hashes = {sha256 = "c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}}, -] -marker = "implementation_name == \"pypy\" and \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "pycparser; implementation_name != \"PyPy\"", -] - -[[packages]] -name = "cfgv" -version = "3.5.0" -requires-python = ">=3.10" -sdist = {name = "cfgv-3.5.0.tar.gz", url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hashes = {sha256 = "d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132"}} -wheels = [ - {name = "cfgv-3.5.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl",hashes = {sha256 = "a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0"}}, -] -marker = "\"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "charset-normalizer" -version = "3.4.7" -requires-python = ">=3.7" -sdist = {name = "charset_normalizer-3.4.7.tar.gz", url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hashes = {sha256 = "ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5"}} -wheels = [ - {name = "charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl",hashes = {sha256 = "c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl",hashes = {sha256 = "c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",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",hashes = {sha256 = "3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl",hashes = {sha256 = "a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl",hashes = {sha256 = "e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl",hashes = {sha256 = "d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl",hashes = {sha256 = "5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl",hashes = {sha256 = "92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl",hashes = {sha256 = "67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl",hashes = {sha256 = "effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl",hashes = {sha256 = "a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",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",hashes = {sha256 = "3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl",hashes = {sha256 = "cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl",hashes = {sha256 = "8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl",hashes = {sha256 = "c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c"}}, - {name = "charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl",hashes = {sha256 = "f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",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",hashes = {sha256 = "e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl",hashes = {sha256 = "481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl",hashes = {sha256 = "f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl",hashes = {sha256 = "3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl",hashes = {sha256 = "4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl",hashes = {sha256 = "3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110"}}, - {name = "charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl",hashes = {sha256 = "80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl",hashes = {sha256 = "203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",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",hashes = {sha256 = "298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl",hashes = {sha256 = "0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl",hashes = {sha256 = "aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl",hashes = {sha256 = "fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl",hashes = {sha256 = "2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl",hashes = {sha256 = "5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6"}}, - {name = "charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl",hashes = {sha256 = "56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl",hashes = {sha256 = "65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",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",hashes = {sha256 = "08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl",hashes = {sha256 = "38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl",hashes = {sha256 = "1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl",hashes = {sha256 = "adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl",hashes = {sha256 = "8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00"}}, - {name = "charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl",hashes = {sha256 = "d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1"}}, - {name = "charset_normalizer-3.4.7-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl",hashes = {sha256 = "3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "click" -version = "8.3.2" -requires-python = ">=3.10" -sdist = {name = "click-8.3.2.tar.gz", url = "https://files.pythonhosted.org/packages/57/75/31212c6bf2503fdf920d87fee5d7a86a2e3bcf444984126f13d8e4016804/click-8.3.2.tar.gz", hashes = {sha256 = "14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5"}} -wheels = [ - {name = "click-8.3.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/e4/20/71885d8b97d4f3dde17b1fdb92dbd4908b00541c5a3379787137285f602e/click-8.3.2-py3-none-any.whl",hashes = {sha256 = "1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "colorama; platform_system == \"Windows\"", -] - -[[packages]] -name = "colorama" -version = "0.4.6" -requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -sdist = {name = "colorama-0.4.6.tar.gz", url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hashes = {sha256 = "08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}} -wheels = [ - {name = "colorama-0.4.6-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl",hashes = {sha256 = "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}}, -] -marker = "\"docs\" in extras or \"test\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "comm" -version = "0.2.3" -requires-python = ">=3.8" -sdist = {name = "comm-0.2.3.tar.gz", url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hashes = {sha256 = "2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971"}} -wheels = [ - {name = "comm-0.2.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl",hashes = {sha256 = "c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "contourpy" -version = "1.3.3" -requires-python = ">=3.11" -sdist = {name = "contourpy-1.3.3.tar.gz", url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hashes = {sha256 = "083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880"}} -wheels = [ - {name = "contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a"}}, - {name = "contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77"}}, - {name = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5"}}, - {name = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4"}}, - {name = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36"}}, - {name = "contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3"}}, - {name = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b"}}, - {name = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36"}}, - {name = "contourpy-1.3.3-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl",hashes = {sha256 = "66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d"}}, - {name = "contourpy-1.3.3-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl",hashes = {sha256 = "cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd"}}, - {name = "contourpy-1.3.3-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl",hashes = {sha256 = "95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339"}}, - {name = "contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772"}}, - {name = "contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77"}}, - {name = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13"}}, - {name = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe"}}, - {name = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f"}}, - {name = "contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0"}}, - {name = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4"}}, - {name = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f"}}, - {name = "contourpy-1.3.3-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl",hashes = {sha256 = "e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae"}}, - {name = "contourpy-1.3.3-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc"}}, - {name = "contourpy-1.3.3-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b"}}, - {name = "contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5"}}, - {name = "contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1"}}, - {name = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286"}}, - {name = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5"}}, - {name = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67"}}, - {name = "contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9"}}, - {name = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659"}}, - {name = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7"}}, - {name = "contourpy-1.3.3-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl",hashes = {sha256 = "b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d"}}, - {name = "contourpy-1.3.3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263"}}, - {name = "contourpy-1.3.3-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl",hashes = {sha256 = "fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9"}}, - {name = "contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d"}}, - {name = "contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216"}}, - {name = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae"}}, - {name = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20"}}, - {name = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99"}}, - {name = "contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b"}}, - {name = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a"}}, - {name = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e"}}, - {name = "contourpy-1.3.3-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl",hashes = {sha256 = "283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3"}}, - {name = "contourpy-1.3.3-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8"}}, - {name = "contourpy-1.3.3-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301"}}, - {name = "contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb"}}, - {name = "contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6"}}, - {name = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7"}}, - {name = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8"}}, - {name = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea"}}, - {name = "contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1"}}, - {name = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7"}}, - {name = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411"}}, - {name = "contourpy-1.3.3-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl",hashes = {sha256 = "023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69"}}, - {name = "contourpy-1.3.3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b"}}, - {name = "contourpy-1.3.3-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl",hashes = {sha256 = "07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc"}}, - {name = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}}, - {name = "contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381"}}, - {name = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7"}}, - {name = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1"}}, - {name = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a"}}, - {name = "contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db"}}, - {name = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620"}}, - {name = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f"}}, - {name = "contourpy-1.3.3-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl",hashes = {sha256 = "fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff"}}, - {name = "contourpy-1.3.3-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl",hashes = {sha256 = "3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42"}}, - {name = "contourpy-1.3.3-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl",hashes = {sha256 = "15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470"}}, - {name = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497"}}, - {name = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8"}}, - {name = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e"}}, - {name = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989"}}, - {name = "contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl",hashes = {sha256 = "3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "numpy>=1.25", -] - -[[packages]] -name = "coverage" -version = "7.13.5" -requires-python = ">=3.10" -sdist = {name = "coverage-7.13.5.tar.gz", url = "https://files.pythonhosted.org/packages/9d/e0/70553e3000e345daff267cec284ce4cbf3fc141b6da229ac52775b5428f1/coverage-7.13.5.tar.gz", hashes = {sha256 = "c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179"}} -wheels = [ - {name = "coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/8e/77/39703f0d1d4b478bfd30191d3c14f53caf596fac00efb3f8f6ee23646439/coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl",hashes = {sha256 = "fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f"}}, - {name = "coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e"}}, - {name = "coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a"}}, - {name = "coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",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",hashes = {sha256 = "6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510"}}, - {name = "coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247"}}, - {name = "coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6"}}, - {name = "coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/3b/c4/b5fd1d4b7bf8d0e75d997afd3925c59ba629fc8616f1b3aae7605132e256/coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0"}}, - {name = "coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/f8/66/6ea21f910e92d69ef0b1c3346ea5922a51bad4446c9126db2ae96ee24c4c/coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882"}}, - {name = "coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/9e/ea/879c83cb5d61aa2a35fb80e72715e92672daef8191b84911a643f533840c/coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl",hashes = {sha256 = "0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740"}}, - {name = "coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/8a/fb/616d95d3adb88b9803b275580bdeee8bd1b69a886d057652521f83d7322f/coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16"}}, - {name = "coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/1c/93/25e6917c90ec1c9a56b0b26f6cad6408e5f13bb6b35d484a0d75c9cf000d/coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl",hashes = {sha256 = "cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0"}}, - {name = "coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/fc/7b/dc1776b0464145a929deed214aef9fb1493f159b59ff3c7eeeedf91eddd0/coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0"}}, - {name = "coverage-7.13.5-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/ea/fb/99cbbc56a26e07762a2740713f3c8f9f3f3106e3a3dd8cc4474954bccd34/coverage-7.13.5-cp314-cp314-win32.whl",hashes = {sha256 = "35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc"}}, - {name = "coverage-7.13.5-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl",hashes = {sha256 = "2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633"}}, - {name = "coverage-7.13.5-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/2c/f2/24d84e1dfe70f8ac9fdf30d338239860d0d1d5da0bda528959d0ebc9da28/coverage-7.13.5-cp314-cp314-win_arm64.whl",hashes = {sha256 = "1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8"}}, - {name = "coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/60/5b/4a168591057b3668c2428bff25dd3ebc21b629d666d90bcdfa0217940e84/coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b"}}, - {name = "coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/f5/21/1fd5c4dbfe4a58b6b99649125635df46decdfd4a784c3cd6d410d303e370/coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c"}}, - {name = "coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9"}}, - {name = "coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",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",hashes = {sha256 = "9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29"}}, - {name = "coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607"}}, - {name = "coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90"}}, - {name = "coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/7a/5e/31484d62cbd0eabd3412e30d74386ece4a0837d4f6c3040a653878bfc019/coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3"}}, - {name = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/e9/d8/49a72d6de146eebb0b7e48cc0f4bc2c0dd858e3d4790ab2b39a2872b62bd/coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab"}}, - {name = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/06/3b/0351f1bd566e6e4dd39e978efe7958bde1d32f879e85589de147654f57bb/coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl",hashes = {sha256 = "8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562"}}, - {name = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/5d/ce/796a2a2f4017f554d7810f5c573449b35b1e46788424a548d4d19201b222/coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2"}}, - {name = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/3d/16/d5ae91455541d1a78bc90abf495be600588aff8f6db5c8b0dae739fa39c9/coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea"}}, - {name = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/48/11/07f413dba62db21fb3fad5d0de013a50e073cc4e2dc4306e770360f6dfc8/coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a"}}, - {name = "coverage-7.13.5-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/91/15/d792371332eb4663115becf4bad47e047d16234b1aff687b1b18c58d60ae/coverage-7.13.5-cp314-cp314t-win32.whl",hashes = {sha256 = "0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215"}}, - {name = "coverage-7.13.5-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/db/51/37221f59a111dca5e85be7dbf09696323b5b9f13ff65e0641d535ed06ea8/coverage-7.13.5-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43"}}, - {name = "coverage-7.13.5-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/54/83/6acacc889de8987441aa7d5adfbdbf33d288dad28704a67e574f1df9bcbb/coverage-7.13.5-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45"}}, - {name = "coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1"}}, - {name = "coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3"}}, - {name = "coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26"}}, - {name = "coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",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",hashes = {sha256 = "78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3"}}, - {name = "coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b"}}, - {name = "coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a"}}, - {name = "coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/1b/66/c1dceb7b9714473800b075f5c8a84f4588f887a90eb8645282031676e242/coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969"}}, - {name = "coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b7/62/5502b73b97aa2e53ea22a39cf8649ff44827bef76d90bf638777daa27a9d/coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161"}}, - {name = "coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/7d/37/7792c2d69854397ca77a55c4646e5897c467928b0e27f2d235d83b5d08c6/coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15"}}, - {name = "coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/a3/23/bc866fb6163be52a8a9e5d708ba0d3b1283c12158cefca0a8bbb6e247a43/coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1"}}, - {name = "coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/7d/8b/ef67e1c222ef49860701d346b8bbb70881bef283bd5f6cbba68a39a086c7/coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl",hashes = {sha256 = "2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6"}}, - {name = "coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/46/0d/866d1f74f0acddbb906db212e096dee77a8e2158ca5e6bb44729f9d93298/coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17"}}, - {name = "coverage-7.13.5-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/7a/f5/be742fec31118f02ce42b21c6af187ad6a344fed546b56ca60caacc6a9a0/coverage-7.13.5-cp313-cp313-win32.whl",hashes = {sha256 = "ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85"}}, - {name = "coverage-7.13.5-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl",hashes = {sha256 = "631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b"}}, - {name = "coverage-7.13.5-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/48/af/fea819c12a095781f6ccd504890aaddaf88b8fab263c4940e82c7b770124/coverage-7.13.5-cp313-cp313-win_arm64.whl",hashes = {sha256 = "f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664"}}, - {name = "coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/23/d2/17879af479df7fbbd44bd528a31692a48f6b25055d16482fdf5cdb633805/coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d"}}, - {name = "coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/5b/4c/d20e554f988c8f91d6a02c5118f9abbbf73a8768a3048cb4962230d5743f/coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0"}}, - {name = "coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806"}}, - {name = "coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",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",hashes = {sha256 = "4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3"}}, - {name = "coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9"}}, - {name = "coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd"}}, - {name = "coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/5b/02/353ca81d36779bd108f6d384425f7139ac3c58c750dcfaafe5d0bee6436b/coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606"}}, - {name = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/2c/16/2e79106d5749bcaf3aee6d309123548e3276517cd7851faa8da213bc61bf/coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e"}}, - {name = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/29/c7/c29e0c59ffa6942030ae6f50b88ae49988e7e8da06de7ecdbf49c6d4feae/coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl",hashes = {sha256 = "f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0"}}, - {name = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/40/48/097cdc3db342f34006a308ab41c3a7c11c3f0d84750d340f45d88a782e00/coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87"}}, - {name = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/bb/1f/4994af354689e14fd03a75f8ec85a9a68d94e0188bbdab3fc1516b55e512/coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479"}}, - {name = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/22/c6/9bb9ef55903e628033560885f5c31aa227e46878118b63ab15dc7ba87797/coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2"}}, - {name = "coverage-7.13.5-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/14/4f/f5df9007e50b15e53e01edea486814783a7f019893733d9e4d6caad75557/coverage-7.13.5-cp313-cp313t-win32.whl",hashes = {sha256 = "67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a"}}, - {name = "coverage-7.13.5-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/e1/98/aa7fccaa97d0f3192bec013c4e6fd6d294a6ed44b640e6bb61f479e00ed5/coverage-7.13.5-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819"}}, - {name = "coverage-7.13.5-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/3d/8b/e5c469f7352651e5f013198e9e21f97510b23de957dd06a84071683b4b60/coverage-7.13.5-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911"}}, - {name = "coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/a0/c3/a396306ba7db865bf96fc1fb3b7fd29bcbf3d829df642e77b13555163cd6/coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01"}}, - {name = "coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422"}}, - {name = "coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f"}}, - {name = "coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",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",hashes = {sha256 = "03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5"}}, - {name = "coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376"}}, - {name = "coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256"}}, - {name = "coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/81/bd/73ddf85f93f7e6fa83e77ccecb6162d9415c79007b4bc124008a4995e4a7/coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c"}}, - {name = "coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/a0/81/278aff4e8dec4926a0bcb9486320752811f543a3ce5b602cc7a29978d073/coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5"}}, - {name = "coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/70/ee/fe1621488e2e0a58d7e94c4800f0d96f79671553488d401a612bebae324b/coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09"}}, - {name = "coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/37/a6/f79fb37aa104b562207cc23cb5711ab6793608e246cae1e93f26b2236ed9/coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9"}}, - {name = "coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/75/f0/ed15262a58ec81ce457ceb717b7f78752a1713556b19081b76e90896e8d4/coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl",hashes = {sha256 = "7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf"}}, - {name = "coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/0f/e9/9129958f20e7e9d4d56d51d42ccf708d15cac355ff4ac6e736e97a9393d2/coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c"}}, - {name = "coverage-7.13.5-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/a4/d7/0ad9b15812d81272db94379fe4c6df8fd17781cc7671fdfa30c76ba5ff7b/coverage-7.13.5-cp312-cp312-win32.whl",hashes = {sha256 = "bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf"}}, - {name = "coverage-7.13.5-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl",hashes = {sha256 = "d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810"}}, - {name = "coverage-7.13.5-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/d4/fa/2238c2ad08e35cf4f020ea721f717e09ec3152aea75d191a7faf3ef009a8/coverage-7.13.5-cp312-cp312-win_arm64.whl",hashes = {sha256 = "bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de"}}, - {name = "coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/4b/37/d24c8f8220ff07b839b2c043ea4903a33b0f455abe673ae3c03bbdb7f212/coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d"}}, - {name = "coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/35/8b/cd129b0ca4afe886a6ce9d183c44d8301acbd4ef248622e7c49a23145605/coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587"}}, - {name = "coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",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",hashes = {sha256 = "0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642"}}, - {name = "coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",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",hashes = {sha256 = "ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b"}}, - {name = "coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686"}}, - {name = "coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",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",hashes = {sha256 = "4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743"}}, - {name = "coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/e5/32/d0d7cc8168f91ddab44c0ce4806b969df5f5fdfdbb568eaca2dbc2a04936/coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75"}}, - {name = "coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/4d/06/a055311d891ddbe231cd69fdd20ea4be6e3603ffebddf8704b8ca8e10a3c/coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209"}}, - {name = "coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/d6/f6/d0fd2d21e29a657b5f77a2fe7082e1568158340dceb941954f776dce1b7b/coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a"}}, - {name = "coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/4e/ab/0d7fb2efc2e9a5eb7ddcc6e722f834a69b454b7e6e5888c3a8567ecffb31/coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e"}}, - {name = "coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/ba/6f/7467b917bbf5408610178f62a49c0ed4377bb16c1657f689cc61470da8ce/coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl",hashes = {sha256 = "7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd"}}, - {name = "coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/75/2c/1172fb689df92135f5bfbbd69fc83017a76d24ea2e2f3a1154007e2fb9f8/coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8"}}, - {name = "coverage-7.13.5-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/67/21/9ac389377380a07884e3b48ba7a620fcd9dbfaf1d40565facdc6b36ec9ef/coverage-7.13.5-cp311-cp311-win32.whl",hashes = {sha256 = "259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf"}}, - {name = "coverage-7.13.5-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/af/7f/4cd8a92531253f9d7c1bbecd9fa1b472907fb54446ca768c59b531248dc5/coverage-7.13.5-cp311-cp311-win_amd64.whl",hashes = {sha256 = "258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9"}}, - {name = "coverage-7.13.5-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/12/a6/1d3f6155fb0010ca68eba7fe48ca6c9da7385058b77a95848710ecf189b1/coverage-7.13.5-cp311-cp311-win_arm64.whl",hashes = {sha256 = "bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028"}}, - {name = "coverage-7.13.5-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/9e/ee/a4cf96b8ce1e566ed238f0659ac2d3f007ed1d14b181bcb684e19561a69a/coverage-7.13.5-py3-none-any.whl",hashes = {sha256 = "34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61"}}, -] -marker = "\"test\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "cycler" -version = "0.12.1" -requires-python = ">=3.8" -sdist = {name = "cycler-0.12.1.tar.gz", url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hashes = {sha256 = "88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}} -wheels = [ - {name = "cycler-0.12.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl",hashes = {sha256 = "85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "debugpy" -version = "1.8.20" -requires-python = ">=3.8" -sdist = {name = "debugpy-1.8.20.tar.gz", url = "https://files.pythonhosted.org/packages/e0/b7/cd8080344452e4874aae67c40d8940e2b4d47b01601a8fd9f44786c757c7/debugpy-1.8.20.tar.gz", hashes = {sha256 = "55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33"}} -wheels = [ - {name = "debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl",url = "https://files.pythonhosted.org/packages/33/2e/f6cb9a8a13f5058f0a20fe09711a7b726232cd5a78c6a7c05b2ec726cff9/debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl",hashes = {sha256 = "9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173"}}, - {name = "debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl",url = "https://files.pythonhosted.org/packages/c5/56/6ddca50b53624e1ca3ce1d1e49ff22db46c47ea5fb4c0cc5c9b90a616364/debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl",hashes = {sha256 = "077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad"}}, - {name = "debugpy-1.8.20-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/c5/d9/d64199c14a0d4c476df46c82470a3ce45c8d183a6796cfb5e66533b3663c/debugpy-1.8.20-cp314-cp314-win32.whl",hashes = {sha256 = "352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f"}}, - {name = "debugpy-1.8.20-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/e0/d9/1f07395b54413432624d61524dfd98c1a7c7827d2abfdb8829ac92638205/debugpy-1.8.20-cp314-cp314-win_amd64.whl",hashes = {sha256 = "a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be"}}, - {name = "debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl",url = "https://files.pythonhosted.org/packages/15/e2/fc500524cc6f104a9d049abc85a0a8b3f0d14c0a39b9c140511c61e5b40b/debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl",hashes = {sha256 = "5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a"}}, - {name = "debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl",url = "https://files.pythonhosted.org/packages/90/83/fb33dcea789ed6018f8da20c5a9bc9d82adc65c0c990faed43f7c955da46/debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl",hashes = {sha256 = "84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf"}}, - {name = "debugpy-1.8.20-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/a6/25/b1e4a01bfb824d79a6af24b99ef291e24189080c93576dfd9b1a2815cd0f/debugpy-1.8.20-cp313-cp313-win32.whl",hashes = {sha256 = "da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393"}}, - {name = "debugpy-1.8.20-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl",hashes = {sha256 = "eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7"}}, - {name = "debugpy-1.8.20-cp312-cp312-macosx_15_0_universal2.whl",url = "https://files.pythonhosted.org/packages/14/57/7f34f4736bfb6e00f2e4c96351b07805d83c9a7b33d28580ae01374430f7/debugpy-1.8.20-cp312-cp312-macosx_15_0_universal2.whl",hashes = {sha256 = "4ae3135e2089905a916909ef31922b2d733d756f66d87345b3e5e52b7a55f13d"}}, - {name = "debugpy-1.8.20-cp312-cp312-manylinux_2_34_x86_64.whl",url = "https://files.pythonhosted.org/packages/ab/78/b193a3975ca34458f6f0e24aaf5c3e3da72f5401f6054c0dfd004b41726f/debugpy-1.8.20-cp312-cp312-manylinux_2_34_x86_64.whl",hashes = {sha256 = "88f47850a4284b88bd2bfee1f26132147d5d504e4e86c22485dfa44b97e19b4b"}}, - {name = "debugpy-1.8.20-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/c1/55/f14deb95eaf4f30f07ef4b90a8590fc05d9e04df85ee379712f6fb6736d7/debugpy-1.8.20-cp312-cp312-win32.whl",hashes = {sha256 = "4057ac68f892064e5f98209ab582abfee3b543fb55d2e87610ddc133a954d390"}}, - {name = "debugpy-1.8.20-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a1/39/2bef246368bd42f9bd7cba99844542b74b84dacbdbea0833e610f384fee8/debugpy-1.8.20-cp312-cp312-win_amd64.whl",hashes = {sha256 = "a1a8f851e7cf171330679ef6997e9c579ef6dd33c9098458bd9986a0f4ca52e3"}}, - {name = "debugpy-1.8.20-cp311-cp311-macosx_15_0_universal2.whl",url = "https://files.pythonhosted.org/packages/51/56/c3baf5cbe4dd77427fd9aef99fcdade259ad128feeb8a786c246adb838e5/debugpy-1.8.20-cp311-cp311-macosx_15_0_universal2.whl",hashes = {sha256 = "eada6042ad88fa1571b74bd5402ee8b86eded7a8f7b827849761700aff171f1b"}}, - {name = "debugpy-1.8.20-cp311-cp311-manylinux_2_34_x86_64.whl",url = "https://files.pythonhosted.org/packages/9a/7d/4fa79a57a8e69fe0d9763e98d1110320f9ecd7f1f362572e3aafd7417c9d/debugpy-1.8.20-cp311-cp311-manylinux_2_34_x86_64.whl",hashes = {sha256 = "7de0b7dfeedc504421032afba845ae2a7bcc32ddfb07dae2c3ca5442f821c344"}}, - {name = "debugpy-1.8.20-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/7d/f2/1e8f8affe51e12a26f3a8a8a4277d6e60aa89d0a66512f63b1e799d424a4/debugpy-1.8.20-cp311-cp311-win32.whl",hashes = {sha256 = "773e839380cf459caf73cc533ea45ec2737a5cc184cf1b3b796cd4fd98504fec"}}, - {name = "debugpy-1.8.20-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d5/92/1cb532e88560cbee973396254b21bece8c5d7c2ece958a67afa08c9f10dc/debugpy-1.8.20-cp311-cp311-win_amd64.whl",hashes = {sha256 = "1f7650546e0eded1902d0f6af28f787fa1f1dbdbc97ddabaf1cd963a405930cb"}}, - {name = "debugpy-1.8.20-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl",hashes = {sha256 = "5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "decorator" -version = "5.2.1" -requires-python = ">=3.8" -sdist = {name = "decorator-5.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hashes = {sha256 = "65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}} -wheels = [ - {name = "decorator-5.2.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl",hashes = {sha256 = "d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "defusedxml" -version = "0.7.1" -requires-python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -sdist = {name = "defusedxml-0.7.1.tar.gz", url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hashes = {sha256 = "1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}} -wheels = [ - {name = "defusedxml-0.7.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl",hashes = {sha256 = "a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "dill" -version = "0.4.1" -requires-python = ">=3.9" -sdist = {name = "dill-0.4.1.tar.gz", url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hashes = {sha256 = "423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa"}} -wheels = [ - {name = "dill-0.4.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl",hashes = {sha256 = "1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d"}}, -] -marker = "python_version >= \"3.11\" and \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "distlib" -version = "0.4.0" -sdist = {name = "distlib-0.4.0.tar.gz", url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hashes = {sha256 = "feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}} -wheels = [ - {name = "distlib-0.4.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl",hashes = {sha256 = "9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}}, -] -marker = "\"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "docutils" -version = "0.22.4" -requires-python = ">=3.9" -sdist = {name = "docutils-0.22.4.tar.gz", url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hashes = {sha256 = "4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968"}} -wheels = [ - {name = "docutils-0.22.4-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl",hashes = {sha256 = "d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "executing" -version = "2.2.1" -requires-python = ">=3.8" -sdist = {name = "executing-2.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hashes = {sha256 = "3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4"}} -wheels = [ - {name = "executing-2.2.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl",hashes = {sha256 = "760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "fastjsonschema" -version = "2.21.2" -sdist = {name = "fastjsonschema-2.21.2.tar.gz", url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hashes = {sha256 = "b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"}} -wheels = [ - {name = "fastjsonschema-2.21.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl",hashes = {sha256 = "1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "filelock" -version = "3.28.0" -requires-python = ">=3.10" -sdist = {name = "filelock-3.28.0.tar.gz", url = "https://files.pythonhosted.org/packages/d6/17/6e8890271880903e3538660a21d63a6c1fea969ac71d0d6b608b78727fa9/filelock-3.28.0.tar.gz", hashes = {sha256 = "4ed1010aae813c4ee8d9c660e4792475ee60c4a0ba76073ceaf862bd317e3ca6"}} -wheels = [ - {name = "filelock-3.28.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/3b/21/2f728888c45033d34a417bfcd248ea2564c9e08ab1bfd301377cf05d5586/filelock-3.28.0-py3-none-any.whl",hashes = {sha256 = "de9af6712788e7171df1b28b15eba2446c69721433fa427a9bee07b17820a9db"}}, -] -marker = "\"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "fonttools" -version = "4.62.1" -requires-python = ">=3.10" -sdist = {name = "fonttools-4.62.1.tar.gz", url = "https://files.pythonhosted.org/packages/9a/08/7012b00a9a5874311b639c3920270c36ee0c445b69d9989a85e5c92ebcb0/fonttools-4.62.1.tar.gz", hashes = {sha256 = "e54c75fd6041f1122476776880f7c3c3295ffa31962dc6ebe2543c00dca58b5d"}} -wheels = [ - {name = "fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl",hashes = {sha256 = "fa1d16210b6b10a826d71bed68dd9ec24a9e218d5a5e2797f37c573e7ec215ca"}}, - {name = "fonttools-4.62.1-cp314-cp314-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/4b/b2/e521803081f8dc35990816b82da6360fa668a21b44da4b53fc9e77efcd62/fonttools-4.62.1-cp314-cp314-macosx_10_15_x86_64.whl",hashes = {sha256 = "aa69d10ed420d8121118e628ad47d86e4caa79ba37f968597b958f6cceab7eca"}}, - {name = "fonttools-4.62.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "bd13b7999d59c5eb1c2b442eb2d0c427cb517a0b7a1f5798fc5c9e003f5ff782"}}, - {name = "fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "8d337fdd49a79b0d51c4da87bc38169d21c3abbf0c1aa9367eff5c6656fb6dae"}}, - {name = "fonttools-4.62.1-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/70/b9/ac677cb07c24c685cf34f64e140617d58789d67a3dd524164b63648c6114/fonttools-4.62.1-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d241cdc4a67b5431c6d7f115fdf63335222414995e3a1df1a41e1182acd4bcc7"}}, - {name = "fonttools-4.62.1-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/e6/10/11c08419a14b85b7ca9a9faca321accccc8842dd9e0b1c8a72908de05945/fonttools-4.62.1-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "c05557a78f8fa514da0f869556eeda40887a8abc77c76ee3f74cf241778afd5a"}}, - {name = "fonttools-4.62.1-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/4e/3c/12eea4a4cf054e7ab058ed5ceada43b46809fce2bf319017c4d63ae55bb4/fonttools-4.62.1-cp314-cp314-win32.whl",hashes = {sha256 = "49a445d2f544ce4a69338694cad575ba97b9a75fff02720da0882d1a73f12800"}}, - {name = "fonttools-4.62.1-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-win_amd64.whl",hashes = {sha256 = "1eecc128c86c552fb963fe846ca4e011b1be053728f798185a1687502f6d398e"}}, - {name = "fonttools-4.62.1-cp314-cp314t-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/42/c5/4d2ed3ca6e33617fc5624467da353337f06e7f637707478903c785bd8e20/fonttools-4.62.1-cp314-cp314t-macosx_10_15_universal2.whl",hashes = {sha256 = "1596aeaddf7f78e21e68293c011316a25267b3effdaccaf4d59bc9159d681b82"}}, - {name = "fonttools-4.62.1-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/1f/e9/7ab11ddfda48ed0f89b13380e5595ba572619c27077be0b2c447a63ff351/fonttools-4.62.1-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "8f8fca95d3bb3208f59626a4b0ea6e526ee51f5a8ad5d91821c165903e8d9260"}}, - {name = "fonttools-4.62.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "ee91628c08e76f77b533d65feb3fbe6d9dad699f95be51cf0d022db94089cdc4"}}, - {name = "fonttools-4.62.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/37/dc/8ccd45033fffd74deb6912fa1ca524643f584b94c87a16036855b498a1ed/fonttools-4.62.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "5f37df1cac61d906e7b836abe356bc2f34c99d4477467755c216b72aa3dc748b"}}, - {name = "fonttools-4.62.1-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/99/eb/e618adefb839598d25ac8136cd577925d6c513dc0d931d93b8af956210f0/fonttools-4.62.1-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "92bb00a947e666169c99b43753c4305fc95a890a60ef3aeb2a6963e07902cc87"}}, - {name = "fonttools-4.62.1-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/d9/5f/9b5c9bfaa8ec82def8d8168c4f13615990d6ce5996fe52bd49bfb5e05134/fonttools-4.62.1-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "bdfe592802ef939a0e33106ea4a318eeb17822c7ee168c290273cbd5fabd746c"}}, - {name = "fonttools-4.62.1-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/90/aa/dfbbe24c6a6afc5c203d90cc0343e24bcbb09e76d67c4d6eef8c2558d7ba/fonttools-4.62.1-cp314-cp314t-win32.whl",hashes = {sha256 = "b820fcb92d4655513d8402d5b219f94481c4443d825b4372c75a2072aa4b357a"}}, - {name = "fonttools-4.62.1-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/13/6f/ae9c4e4dd417948407b680855c2c7790efb52add6009aaecff1e3bc50e8e/fonttools-4.62.1-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "59b372b4f0e113d3746b88985f1c796e7bf830dd54b28374cd85c2b8acd7583e"}}, - {name = "fonttools-4.62.1-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/3b/56/6f389de21c49555553d6a5aeed5ac9767631497ac836c4f076273d15bd72/fonttools-4.62.1-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "c22b1014017111c401469e3acc5433e6acf6ebcc6aa9efb538a533c800971c79"}}, - {name = "fonttools-4.62.1-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/03/c5/0e3966edd5ec668d41dfe418787726752bc07e2f5fd8c8f208615e61fa89/fonttools-4.62.1-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "68959f5fc58ed4599b44aad161c2837477d7f35f5f79402d97439974faebfebe"}}, - {name = "fonttools-4.62.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "ef46db46c9447103b8f3ff91e8ba009d5fe181b1920a83757a5762551e32bb68"}}, - {name = "fonttools-4.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/e2/98/8b1e801939839d405f1f122e7d175cebe9aeb4e114f95bfc45e3152af9a7/fonttools-4.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "6706d1cb1d5e6251a97ad3c1b9347505c5615c112e66047abbef0f8545fa30d1"}}, - {name = "fonttools-4.62.1-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/46/76/7d051671e938b1881670528fec69cc4044315edd71a229c7fd712eaa5119/fonttools-4.62.1-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "2e7abd2b1e11736f58c1de27819e1955a53267c21732e78243fa2fa2e5c1e069"}}, - {name = "fonttools-4.62.1-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/1f/ae/b41f8628ec0be3c1b934fc12b84f4576a5c646119db4d3bdd76a217c90b5/fonttools-4.62.1-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "403d28ce06ebfc547fbcb0cb8b7f7cc2f7a2d3e1a67ba9a34b14632df9e080f9"}}, - {name = "fonttools-4.62.1-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/f2/f6/53a1e9469331a23dcc400970a27a4caa3d9f6edbf5baab0260285238b884/fonttools-4.62.1-cp313-cp313-win32.whl",hashes = {sha256 = "93c316e0f5301b2adbe6a5f658634307c096fd5aae60a5b3412e4f3e1728ab24"}}, - {name = "fonttools-4.62.1-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/38/60/35186529de1db3c01f5ad625bde07c1f576305eab6d86bbda4c58445f721/fonttools-4.62.1-cp313-cp313-win_amd64.whl",hashes = {sha256 = "7aa21ff53e28a9c2157acbc44e5b401149d3c9178107130e82d74ceb500e5056"}}, - {name = "fonttools-4.62.1-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/47/d4/dbacced3953544b9a93088cc10ef2b596d348c983d5c67a404fa41ec51ba/fonttools-4.62.1-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "90365821debbd7db678809c7491ca4acd1e0779b9624cdc6ddaf1f31992bf974"}}, - {name = "fonttools-4.62.1-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/66/9e/a769c8e99b81e5a87ab7e5e7236684de4e96246aae17274e5347d11ebd78/fonttools-4.62.1-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "12859ff0b47dd20f110804c3e0d0970f7b832f561630cd879969011541a464a9"}}, - {name = "fonttools-4.62.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "9c125ffa00c3d9003cdaaf7f2c79e6e535628093e14b5de1dccb08859b680936"}}, - {name = "fonttools-4.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/9b/8a/99c8b3c3888c5c474c08dbfd7c8899786de9604b727fcefb055b42c84bba/fonttools-4.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "149f7d84afca659d1a97e39a4778794a2f83bf344c5ee5134e09995086cc2392"}}, - {name = "fonttools-4.62.1-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/d1/c6/0f904540d3e6ab463c1243a0d803504826a11604c72dd58c2949796a1762/fonttools-4.62.1-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "0aa72c43a601cfa9273bb1ae0518f1acadc01ee181a6fc60cd758d7fdadffc04"}}, - {name = "fonttools-4.62.1-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/29/0b/5cbef6588dc9bd6b5c9ad6a4d5a8ca384d0cea089da31711bbeb4f9654a6/fonttools-4.62.1-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "19177c8d96c7c36359266e571c5173bcee9157b59cfc8cb0153c5673dc5a3a7d"}}, - {name = "fonttools-4.62.1-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/4a/47/b3a5342d381595ef439adec67848bed561ab7fdb1019fa522e82101b7d9c/fonttools-4.62.1-cp312-cp312-win32.whl",hashes = {sha256 = "a24decd24d60744ee8b4679d38e88b8303d86772053afc29b19d23bb8207803c"}}, - {name = "fonttools-4.62.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/28/b1/0c2ab56a16f409c6c8a68816e6af707827ad5d629634691ff60a52879792/fonttools-4.62.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "9e7863e10b3de72376280b515d35b14f5eeed639d1aa7824f4cf06779ec65e42"}}, - {name = "fonttools-4.62.1-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/88/39/23ff32561ec8d45a4d48578b4d241369d9270dc50926c017570e60893701/fonttools-4.62.1-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "40975849bac44fb0b9253d77420c6d8b523ac4dcdcefeff6e4d706838a5b80f7"}}, - {name = "fonttools-4.62.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/24/7f/66d3f8a9338a9b67fe6e1739f47e1cd5cee78bd3bc1206ef9b0b982289a5/fonttools-4.62.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "9dde91633f77fa576879a0c76b1d89de373cae751a98ddf0109d54e173b40f14"}}, - {name = "fonttools-4.62.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "6acb4109f8bee00fec985c8c7afb02299e35e9c94b57287f3ea542f28bd0b0a7"}}, - {name = "fonttools-4.62.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/cc/a1/40a5c4d8e28b0851d53a8eeeb46fbd73c325a2a9a165f290a5ed90e6c597/fonttools-4.62.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "1c5c25671ce8805e0d080e2ffdeca7f1e86778c5cbfbeae86d7f866d8830517b"}}, - {name = "fonttools-4.62.1-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/e3/be/d378fca4c65ea1956fee6d90ace6e861776809cbbc5af22388a090c3c092/fonttools-4.62.1-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "a5d8825e1140f04e6c99bb7d37a9e31c172f3bc208afbe02175339e699c710e1"}}, - {name = "fonttools-4.62.1-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/f8/d9/ae6a1d0693a4185a84605679c8a1f719a55df87b9c6e8e817bfdd9ef5936/fonttools-4.62.1-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "268abb1cb221e66c014acc234e872b7870d8b5d4657a83a8f4205094c32d2416"}}, - {name = "fonttools-4.62.1-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/54/6c/af95d9c4efb15cabff22642b608342f2bd67137eea6107202d91b5b03184/fonttools-4.62.1-cp311-cp311-win32.whl",hashes = {sha256 = "942b03094d7edbb99bdf1ae7e9090898cad7bf9030b3d21f33d7072dbcb51a53"}}, - {name = "fonttools-4.62.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d3/97/bf54c5b3f2be34e1f143e6db838dfdc54f2ffa3e68c738934c82f3b2a08d/fonttools-4.62.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "e8514f4924375f77084e81467e63238b095abda5107620f49421c368a6017ed2"}}, - {name = "fonttools-4.62.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/fd/ba/56147c165442cc5ba7e82ecf301c9a68353cede498185869e6e02b4c264f/fonttools-4.62.1-py3-none-any.whl",hashes = {sha256 = "7487782e2113861f4ddcc07c3436450659e3caa5e470b27dc2177cade2d8e7fd"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "formulaic" -version = "1.2.1" -requires-python = ">=3.9" -sdist = {name = "formulaic-1.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/6a/8b/8038d2af289a5cc194fa0a255fe964a1a04e0e6ca4426aed8841a4b571e6/formulaic-1.2.1.tar.gz", hashes = {sha256 = "dc79476baa2d811b35798893eb2f2c1e51edee8d7a9c1429b400e56f4e0beccc"}} -wheels = [ - {name = "formulaic-1.2.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/1a/9d/c2c8b51b32f829a16fe042db30ad1dcef7947bf1dcf77c2cfd7b6f37b83a/formulaic-1.2.1-py3-none-any.whl",hashes = {sha256 = "661d6d2467aa961b9afb3a1e2a187494239793c63eb729e422d1307afa98b43b"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "interface-meta>=1.2.0", - "narwhals>=1.17", - "numpy>=1.20.0", - "pandas>=1.3", - "scipy>=1.6", - "typing-extensions>=4.2.0", - "wrapt>=1.0; python_version < \"3.13\"", - "wrapt>=1.17.0rc1; python_version >= \"3.13\"", -] - -[[packages]] -name = "furo" -version = "2025.12.19" -requires-python = ">=3.8" -sdist = {name = "furo-2025.12.19.tar.gz", url = "https://files.pythonhosted.org/packages/ec/20/5f5ad4da6a5a27c80f2ed2ee9aee3f9e36c66e56e21c00fde467b2f8f88f/furo-2025.12.19.tar.gz", hashes = {sha256 = "188d1f942037d8b37cd3985b955839fea62baa1730087dc29d157677c857e2a7"}} -wheels = [ - {name = "furo-2025.12.19-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/f4/b2/50e9b292b5cac13e9e81272c7171301abc753a60460d21505b606e15cf21/furo-2025.12.19-py3-none-any.whl",hashes = {sha256 = "bb0ead5309f9500130665a26bee87693c41ce4dbdff864dbfb6b0dae4673d24f"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "accessible-pygments>=0.0.5", - "beautifulsoup4", - "pygments>=2.7", - "sphinx-basic-ng>=1.0.0.beta2", - "sphinx<10.0,>=7.0", -] - -[[packages]] -name = "h11" -version = "0.16.0" -requires-python = ">=3.8" -sdist = {name = "h11-0.16.0.tar.gz", url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hashes = {sha256 = "4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}} -wheels = [ - {name = "h11-0.16.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl",hashes = {sha256 = "63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "identify" -version = "2.6.18" -requires-python = ">=3.10" -sdist = {name = "identify-2.6.18.tar.gz", url = "https://files.pythonhosted.org/packages/46/c4/7fb4db12296cdb11893d61c92048fe617ee853f8523b9b296ac03b43757e/identify-2.6.18.tar.gz", hashes = {sha256 = "873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd"}} -wheels = [ - {name = "identify-2.6.18-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl",hashes = {sha256 = "8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737"}}, -] -marker = "\"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "idna" -version = "3.11" -requires-python = ">=3.8" -sdist = {name = "idna-3.11.tar.gz", url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hashes = {sha256 = "795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}} -wheels = [ - {name = "idna-3.11-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl",hashes = {sha256 = "771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "imagesize" -version = "1.5.0" -requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -sdist = {name = "imagesize-1.5.0.tar.gz", url = "https://files.pythonhosted.org/packages/cf/59/4b0dd64676aa6fb4986a755790cb6fc558559cf0084effad516820208ec3/imagesize-1.5.0.tar.gz", hashes = {sha256 = "8bfc5363a7f2133a89f0098451e0bcb1cd71aba4dc02bbcecb39d99d40e1b94f"}} -wheels = [ - {name = "imagesize-1.5.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/1e/b1/a0662b03103c66cf77101a187f396ea91167cd9b7d5d3a2e465ad2c7ee9b/imagesize-1.5.0-py2.py3-none-any.whl",hashes = {sha256 = "32677681b3f434c2cb496f00e89c5a291247b35b1f527589909e008057da5899"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "iniconfig" -version = "2.3.0" -requires-python = ">=3.10" -sdist = {name = "iniconfig-2.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hashes = {sha256 = "c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}} -wheels = [ - {name = "iniconfig-2.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl",hashes = {sha256 = "f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}}, -] -marker = "\"test\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "interface-meta" -version = "1.3.0" -requires-python = ">=3.7,<4.0" -sdist = {name = "interface_meta-1.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/4d/75/10526292b332f3479c246750a96f6ec11a28e297839a9c25583b2aadc119/interface_meta-1.3.0.tar.gz", hashes = {sha256 = "8a4493f8bdb73fb9655dcd5115bc897e207319e36c8835f39c516a2d7e9d79a1"}} -wheels = [ - {name = "interface_meta-1.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/02/3f/a6ec28c88e2d8e54d32598a1e0b5208a4baa72a8e7f6e241beab5731eb9d/interface_meta-1.3.0-py3-none-any.whl",hashes = {sha256 = "de35dc5241431886e709e20a14d6597ed07c9f1e8b4bfcffde2190ca5b700ee8"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "ipykernel" -version = "7.2.0" -requires-python = ">=3.10" -sdist = {name = "ipykernel-7.2.0.tar.gz", url = "https://files.pythonhosted.org/packages/ca/8d/b68b728e2d06b9e0051019640a40a9eb7a88fcd82c2e1b5ce70bef5ff044/ipykernel-7.2.0.tar.gz", hashes = {sha256 = "18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e"}} -wheels = [ - {name = "ipykernel-7.2.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl",hashes = {sha256 = "3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "appnope>=0.1.2; platform_system == \"Darwin\"", - "comm>=0.1.1", - "debugpy>=1.6.5", - "ipython>=7.23.1", - "jupyter-client>=8.8.0", - "jupyter-core!=6.0.*,>=5.1", - "matplotlib-inline>=0.1", - "nest-asyncio>=1.4", - "packaging>=22", - "psutil>=5.7", - "pyzmq>=25", - "tornado>=6.4.1", - "traitlets>=5.4.0", -] - -[[packages]] -name = "ipython" -version = "9.10.1" -requires-python = ">=3.11" -sdist = {name = "ipython-9.10.1.tar.gz", url = "https://files.pythonhosted.org/packages/c5/25/daae0e764047b0a2480c7bbb25d48f4f509b5818636562eeac145d06dfee/ipython-9.10.1.tar.gz", hashes = {sha256 = "e170e9b2a44312484415bdb750492699bf329233b03f2557a9692cce6466ada4"}} -wheels = [ - {name = "ipython-9.10.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/01/09/ba70f8d662d5671687da55ad2cc0064cf795b15e1eea70907532202e7c97/ipython-9.10.1-py3-none-any.whl",hashes = {sha256 = "82d18ae9fb9164ded080c71ef92a182ee35ee7db2395f67616034bebb020a232"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "colorama>=0.4.4; sys_platform == \"win32\"", - "decorator>=4.3.2", - "ipython-pygments-lexers>=1.0.0", - "jedi>=0.18.1", - "matplotlib-inline>=0.1.5", - "pexpect>4.3; sys_platform != \"win32\" and sys_platform != \"emscripten\"", - "prompt-toolkit<3.1.0,>=3.0.41", - "pygments>=2.11.0", - "stack-data>=0.6.0", - "traitlets>=5.13.0", - "typing-extensions>=4.6; python_version < \"3.12\"", -] - -[[packages]] -name = "ipython-pygments-lexers" -version = "1.1.1" -requires-python = ">=3.8" -sdist = {name = "ipython_pygments_lexers-1.1.1.tar.gz", url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hashes = {sha256 = "09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81"}} -wheels = [ - {name = "ipython_pygments_lexers-1.1.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl",hashes = {sha256 = "a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "pygments", -] - -[[packages]] -name = "ipywidgets" -version = "8.1.8" -requires-python = ">=3.7" -sdist = {name = "ipywidgets-8.1.8.tar.gz", url = "https://files.pythonhosted.org/packages/4c/ae/c5ce1edc1afe042eadb445e95b0671b03cee61895264357956e61c0d2ac0/ipywidgets-8.1.8.tar.gz", hashes = {sha256 = "61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668"}} -wheels = [ - {name = "ipywidgets-8.1.8-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl",hashes = {sha256 = "ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "comm>=0.1.3", - "ipython>=6.1.0", - "jupyterlab-widgets~=3.0.15", - "traitlets>=4.3.1", - "widgetsnbextension~=4.0.14", -] - -[[packages]] -name = "isort" -version = "8.0.1" -requires-python = ">=3.10.0" -sdist = {name = "isort-8.0.1.tar.gz", url = "https://files.pythonhosted.org/packages/ef/7c/ec4ab396d31b3b395e2e999c8f46dec78c5e29209fac49d1f4dace04041d/isort-8.0.1.tar.gz", hashes = {sha256 = "171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d"}} -wheels = [ - {name = "isort-8.0.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/3e/95/c7c34aa53c16353c56d0b802fba48d5f5caa2cdee7958acbcb795c830416/isort-8.0.1-py3-none-any.whl",hashes = {sha256 = "28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "jedi" -version = "0.19.2" -requires-python = ">=3.6" -sdist = {name = "jedi-0.19.2.tar.gz", url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hashes = {sha256 = "4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}} -wheels = [ - {name = "jedi-0.19.2-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl",hashes = {sha256 = "a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "parso<0.9.0,>=0.8.4", -] - -[[packages]] -name = "jinja2" -version = "3.1.6" -requires-python = ">=3.7" -sdist = {name = "jinja2-3.1.6.tar.gz", url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hashes = {sha256 = "0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}} -wheels = [ - {name = "jinja2-3.1.6-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl",hashes = {sha256 = "85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "MarkupSafe>=2.0", -] - -[[packages]] -name = "joblib" -version = "1.5.3" -requires-python = ">=3.9" -sdist = {name = "joblib-1.5.3.tar.gz", url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hashes = {sha256 = "8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3"}} -wheels = [ - {name = "joblib-1.5.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl",hashes = {sha256 = "5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "jsonschema" -version = "4.26.0" -requires-python = ">=3.10" -sdist = {name = "jsonschema-4.26.0.tar.gz", url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hashes = {sha256 = "0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}} -wheels = [ - {name = "jsonschema-4.26.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl",hashes = {sha256 = "d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "attrs>=22.2.0", - "jsonschema-specifications>=2023.03.6", - "referencing>=0.28.4", - "rpds-py>=0.25.0", -] - -[[packages]] -name = "jsonschema-specifications" -version = "2025.9.1" -requires-python = ">=3.9" -sdist = {name = "jsonschema_specifications-2025.9.1.tar.gz", url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hashes = {sha256 = "b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}} -wheels = [ - {name = "jsonschema_specifications-2025.9.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl",hashes = {sha256 = "98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "referencing>=0.31.0", -] - -[[packages]] -name = "jupyter-client" -version = "8.8.0" -requires-python = ">=3.10" -sdist = {name = "jupyter_client-8.8.0.tar.gz", url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hashes = {sha256 = "d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e"}} -wheels = [ - {name = "jupyter_client-8.8.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl",hashes = {sha256 = "f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "jupyter-core>=5.1", - "python-dateutil>=2.8.2", - "pyzmq>=25.0", - "tornado>=6.4.1", - "traitlets>=5.3", -] - -[[packages]] -name = "jupyter-core" -version = "5.9.1" -requires-python = ">=3.10" -sdist = {name = "jupyter_core-5.9.1.tar.gz", url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hashes = {sha256 = "4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508"}} -wheels = [ - {name = "jupyter_core-5.9.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl",hashes = {sha256 = "ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "platformdirs>=2.5", - "traitlets>=5.3", -] - -[[packages]] -name = "jupyter-sphinx" -version = "0.5.3" -requires-python = ">=3.8" -sdist = {name = "jupyter_sphinx-0.5.3.tar.gz", url = "https://files.pythonhosted.org/packages/1a/b5/40f540cc9e54ee829f79daac43456a8d5ab4b70c8d26f0b9eca0dfcb4ad5/jupyter_sphinx-0.5.3.tar.gz", hashes = {sha256 = "2e23699a3a1cf5db31b10981da5aa32606ee730f6b73a844d1e76d800756af56"}} -wheels = [ - {name = "jupyter_sphinx-0.5.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/6f/1c/45251d4b9624e42b9e4f369dae2a64f5ea19b9387ba492ceb7be65343dda/jupyter_sphinx-0.5.3-py3-none-any.whl",hashes = {sha256 = "a67b3208d4da5b3508dbb8260d3b359ae476c36c6c642747b78a2520e5be0b05"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "ipykernel>=4.5.1", - "ipython", - "ipywidgets>=7.0.0", - "nbconvert>=5.5", - "nbformat", - "sphinx>=7", -] - -[[packages]] -name = "jupyterlab-pygments" -version = "0.3.0" -requires-python = ">=3.8" -sdist = {name = "jupyterlab_pygments-0.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hashes = {sha256 = "721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}} -wheels = [ - {name = "jupyterlab_pygments-0.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl",hashes = {sha256 = "841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "jupyterlab-widgets" -version = "3.0.16" -requires-python = ">=3.7" -sdist = {name = "jupyterlab_widgets-3.0.16.tar.gz", url = "https://files.pythonhosted.org/packages/26/2d/ef58fed122b268c69c0aa099da20bc67657cdfb2e222688d5731bd5b971d/jupyterlab_widgets-3.0.16.tar.gz", hashes = {sha256 = "423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0"}} -wheels = [ - {name = "jupyterlab_widgets-3.0.16-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl",hashes = {sha256 = "45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "kiwisolver" -version = "1.5.0" -requires-python = ">=3.10" -sdist = {name = "kiwisolver-1.5.0.tar.gz", url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hashes = {sha256 = "d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a"}} -wheels = [ - {name = "kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/e4/d7/060f45052f2a01ad5762c8fdecd6d7a752b43400dc29ff75cd47225a40fd/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl",hashes = {sha256 = "8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/c2/a7/78da680eadd06ff35edef6ef68a1ad273bad3e2a0936c9a885103230aece/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl",hashes = {sha256 = "1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/6b/f0/f768ae564a710135630672981231320bc403cf9152b5596ec5289de0f106/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/e2/9f/1de7aad00697325f05238a5f2eafbd487fb637cc27a558b5367a5f37fb7f/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/5a/c2/297f25141d2e468e0ce7f7a7b92e0cf8918143a0cbd3422c1ad627e85a06/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/b9/d3/f4c73a02eb41520c47610207b21afa8cdd18fdbf64ffd94674ae21c4812d/kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl",hashes = {sha256 = "d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7b/46/d3f2efef7732fcda98d22bf4ad5d3d71d545167a852ca710a494f4c15343/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/3f/ec/2d9756bf2b6d26ae4349b8d3662fb3993f16d80c1f971c179ce862b9dbae/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/8f/9f/876a0a0f2260f1bde92e002b3019a5fabc35e0939c7d945e0fa66185eb20/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl",hashes = {sha256 = "e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/6c/4f/ba3624dfac23a64d54ac4179832860cb537c1b0af06024936e82ca4154a0/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl",hashes = {sha256 = "d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/39/b7/97716b190ab98911b20d10bf92eca469121ec483b8ce0edd314f51bc85af/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl",hashes = {sha256 = "d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e"}}, - {name = "kiwisolver-1.5.0-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/70/15/9b90f7df0e31a003c71649cf66ef61c3c1b862f48c81007fa2383c8bd8d7/kiwisolver-1.5.0-cp314-cp314-win_arm64.whl",hashes = {sha256 = "fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/17/01/7dc8c5443ff42b38e72731643ed7cf1ed9bf01691ae5cdca98501999ed83/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl",hashes = {sha256 = "d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/46/8a/b4ebe46ebaac6a303417fab10c2e165c557ddaff558f9699d302b256bc53/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/60/35/10a844afc5f19d6f567359bf4789e26661755a2f36200d5d1ed8ad0126e5/kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/f8/8a/685b297052dd041dcebce8e8787b58923b6e78acc6115a0dc9189011c44b/kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/9e/80/04865e3d4638ac5bddec28908916df4a3075b8c6cc101786a96803188b96/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/ba/01/77a19cacc0893fa13fafa46d1bba06fb4dc2360b3292baf4b56d8e067b24/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/53/39/bcaf5d0cca50e604cfa9b4e3ae1d64b50ca1ae5b754122396084599ef903/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/d0/7a/72c187abc6975f6978c3e39b7cf67aeb8b3c0a8f9790aa7fd412855e9e1f/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl",hashes = {sha256 = "70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c7/ca/cf5b25783ebbd59143b4371ed0c8428a278abe68d6d0104b01865b1bbd0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/4a/e5/b1f492adc516796e88751282276745340e2a72dcd0d36cf7173e0daf3210/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/e6/e5/9b21fbe91a61b8f409d74a26498706e97a48008bfcd1864373d32a6ba31c/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/b1/02/83f47986138310f95ea95531f851b2a62227c11cbc3e690ae1374fe49f0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl",hashes = {sha256 = "0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/18/43a5f24608d8c313dd189cf838c8e68d75b115567c6279de7796197cfb6a/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/3b/b5/98222136d839b8afabcaa943b09bd05888c2d36355b7e448550211d1fca4/kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681"}}, - {name = "kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/99/a2/ca7dc962848040befed12732dff6acae7fb3c4f6fc4272b3f6c9a30b8713/kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/9d/69/024d6711d5ba575aa65d5538042e99964104e97fa153a9f10bc369182bc2/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/ce/48/adbb40df306f587054a348831220812b9b1d787aff714cfbc8556e38fccd/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a8/3a/d0a972b34e1c63e2409413104216cd1caa02c5a37cb668d1687d466c1c45/kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/2b/0a/7b98e1e119878a27ba8618ca1e18b14f992ff1eda40f47bccccf4de44121/kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/18/d8/55638d89ffd27799d5cc3d8aa28e12f4ce7a64d67b285114dbedc8ea4136/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b8/97/b4c8d0d18421ecceba20ad8701358453b88e32414e6f6950b5a4bad54e65/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/c4/10/f862f94b6389d8957448ec9df59450b81bec4abb318805375c401a1e6892/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/a3/6a/f1650af35821eaf09de398ec0bc2aefc8f211f0cda50204c9f1673741ba9/kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl",hashes = {sha256 = "d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/de/19/d7fb82984b9238115fe629c915007be608ebd23dc8629703d917dbfaffd4/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/7f/b9/46b7f386589fd222dac9e9de9c956ce5bcefe2ee73b4e79891381dda8654/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/92/8b/95e237cf3d9c642960153c769ddcbe278f182c8affb20cecc1cc983e7cc5/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl",hashes = {sha256 = "c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/1b/95/980c9df53501892784997820136c01f62bc1865e31b82b9560f980c0e649/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl",hashes = {sha256 = "fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/cb/32/900647fd0840abebe1561792c6b31e6a7c0e278fc3973d30572a965ca14c/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/be/8a/be60e3bbcf513cc5a50f4a3e88e1dcecebb79c1ad607a7222877becaa101/kiwisolver-1.5.0-cp313-cp313-win_amd64.whl",hashes = {sha256 = "0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276"}}, - {name = "kiwisolver-1.5.0-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/4d/d2/64be2e429eb4fca7f7e1c52a91b12663aeaf25de3895e5cca0f47ef2a8d0/kiwisolver-1.5.0-cp313-cp313-win_arm64.whl",hashes = {sha256 = "fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/b0/69/ce68dd0c85755ae2de490bf015b62f2cea5f6b14ff00a463f9d0774449ff/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl",hashes = {sha256 = "db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/74/aa/937aac021cf9d4349990d47eb319309a51355ed1dbdc9c077cdc9224cb11/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ee/20/3a87fbece2c40ad0f6f0aefa93542559159c5f99831d596050e8afae7a9f/kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/f0/7f/f943879cda9007c45e1f7dba216d705c3a18d6b35830e488b6c6a4e7cdf0/kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/37/f8/4d4f85cc1870c127c88d950913370dd76138482161cd07eabbc450deff01/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/04/0b/65dd2916c84d252b244bd405303220f729e7c17c9d7d33dca6feeff9ffc4/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/39/5c/2606a373247babce9b1d056c03a04b65f3cf5290a8eac5d7bdead0a17e21/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/d5/d1/c6078b5756670658e9192a2ef11e939c92918833d2745f85cd14a6004bdf/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl",hashes = {sha256 = "89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/cb/c8/7def6ddf16eb2b3741d8b172bdaa9af882b03c78e9b0772975408801fa63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/9e/87/2ac1fce0eb1e616fcd3c35caa23e665e9b1948bb984f4764790924594128/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/67/13/c6700ccc6cc218716bfcda4935e4b2997039869b4ad8a94f364c5a3b8e63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/1b/bd/877056304626943ff0f1f44c08f584300c199b887cb3176cd7e34f1515f1/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl",hashes = {sha256 = "fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/75/19/c60626c47bf0f8ac5dcf72c6c98e266d714f2fbbfd50cf6dab5ede3aaa50/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2"}}, - {name = "kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/47/84/6a6d5e5bb8273756c27b7d810d47f7ef2f1f9b9fd23c9ee9a3f8c75c9cef/kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/4d/b2/818b74ebea34dabe6d0c51cb1c572e046730e64844da6ed646d5298c40ce/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/bf/d9/405320f8077e8e1c5c4bd6adc45e1e6edf6d727b6da7f2e2533cf58bff71/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/c8/2f/cebfcdb60fd6a9b0f6b47a9337198bcbad6fbe15e68189b7011fd914911f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/f2/0d/9b782923aada3fafb1d6b84e13121954515c669b18af0c26e7d21f579855/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/27/70/83241b6634b04fe44e892688d5208332bde130f38e610c0418f9ede47ded/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/e4/db/30ed226fb271ae1a6431fc0fe0edffb2efe23cadb01e798caeb9f2ceae8f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl",hashes = {sha256 = "cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ec/bd/c314595208e4c9587652d50959ead9e461995389664e490f4dce7ff0f782/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/c1/43/0499cec932d935229b5543d073c2b87c9c22846aab48881e9d8d6e742a2d/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/3d/6f/79b0d760907965acfd9d61826a3d41f8f093c538f55cd2633d3f0db269f6/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl",hashes = {sha256 = "1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/ab/31/01d0537c41cb75a551a438c3c7a80d0c60d60b81f694dac83dd436aec0d0/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl",hashes = {sha256 = "530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/e4/34/8aefdd0be9cfd00a44509251ba864f5caf2991e36772e61c408007e7f417/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384"}}, - {name = "kiwisolver-1.5.0-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/28/26/192b26196e2316e2bd29deef67e37cdf9870d9af8e085e521afff0fed526/kiwisolver-1.5.0-cp312-cp312-win_arm64.whl",hashes = {sha256 = "f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/12/dd/a495a9c104be1c476f0386e714252caf2b7eca883915422a64c50b88c6f5/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/0a/aa/510dc933d87767584abfe03efa445889996c70c2990f6f87c3ebaa0a18c5/kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/fd/d6/76621246f5165e5372f02f5e6f3f48ea336a8f9e96e43997d45b240ed8cd/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b2/c1/31559ec6fb39a5b48035ce29bb63ade628f321785f38c384dee3e2c08bc1/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/5e/ef/1cb8276f2d29cc6a41e0a042f27946ca347d3a4a75acf85d0a16aa6dcc82/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/4c/e4/5ba3cecd7ce6236ae4a80f67e5d5531287337d0e1f076ca87a5abe4cd5d0/kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl",hashes = {sha256 = "01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/5a/69/dc61f7ae9a2f071f26004ced87f078235b5507ab6e5acd78f40365655034/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/e5/7b/abbe0f1b5afa85f8d084b73e90e5f801c0939eba16ac2e49af7c61a6c28d/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/8a/80/5908ae149d96d81580d604c7f8aefd0e98f4fd728cf172f477e9f2a81744/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl",hashes = {sha256 = "800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/84/08/a78cb776f8c085b7143142ce479859cfec086bd09ee638a317040b6ef420/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/b1/e1/65584da5356ed6cb12c63791a10b208860ac40a83de165cb6a6751a686e3/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/be/6c/28f17390b62b8f2f520e2915095b3c94d88681ecf0041e75389d9667f202/kiwisolver-1.5.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "beb7f344487cdcb9e1efe4b7a29681b74d34c08f0043a327a74da852a6749e7b"}}, - {name = "kiwisolver-1.5.0-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/d8/0e/2ee5debc4f77a625778fec5501ff3e8036fe361b7ee28ae402a485bb9694/kiwisolver-1.5.0-cp311-cp311-win_arm64.whl",hashes = {sha256 = "ad4ae4ffd1ee9cd11357b4c66b612da9888f4f4daf2f36995eda64bd45370cac"}}, - {name = "kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/e9/eb/5fcbbbf9a0e2c3a35effb88831a483345326bbc3a030a3b5b69aee647f84/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232"}}, - {name = "kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c3/9b/e17104555bb4db148fd52327feea1e96be4b88e8e008b029002c281a21ab/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a"}}, - {name = "kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",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",hashes = {sha256 = "be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737"}}, - {name = "kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16"}}, - {name = "kiwisolver-1.5.0-pp311-pypy311_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/0a/dd/8050c947d435c8d4bc94e3252f4d8bb8a76cfb424f043a8680be637a57f1/kiwisolver-1.5.0-pp311-pypy311_pp73-win_amd64.whl",hashes = {sha256 = "59cd8683f575d96df5bb48f6add94afc055012c29e28124fcae2b63661b9efb1"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "lifelines" -version = "0.30.0" -requires-python = ">=3.9" -sdist = {name = "lifelines-0.30.0.tar.gz", url = "https://files.pythonhosted.org/packages/ea/4f/f0b363278d40baf7d7a03217bee839cb880946c62109f243391c8754bb09/lifelines-0.30.0.tar.gz", hashes = {sha256 = "f7f6f6275fcb167fe0f5b1ef98f868993f9c074cb74b1dd6e92736efa854be18"}} -wheels = [ - {name = "lifelines-0.30.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/14/f7/379e185a75ac8166ac70756d0ba68d9a2b02b555c7fde4983246752396bd/lifelines-0.30.0-py3-none-any.whl",hashes = {sha256 = "ac7c602c8aceced9770d3977817c9d99c250ed8cd86f2567fa0d23e4e8014bf9"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "autograd-gamma>=0.3", - "autograd>=1.5", - "formulaic>=0.2.2", - "matplotlib>=3.0", - "numpy>=1.14.0", - "pandas>=2.1", - "scipy>=1.7.0", -] - -[[packages]] -name = "markdown-it-py" -version = "4.0.0" -requires-python = ">=3.10" -sdist = {name = "markdown_it_py-4.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hashes = {sha256 = "cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"}} -wheels = [ - {name = "markdown_it_py-4.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl",hashes = {sha256 = "87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "mdurl~=0.1", -] - -[[packages]] -name = "markupsafe" -version = "3.0.3" -requires-python = ">=3.9" -sdist = {name = "markupsafe-3.0.3.tar.gz", url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hashes = {sha256 = "722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}} -wheels = [ - {name = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}}, - {name = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}}, - {name = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}}, - {name = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}}, - {name = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}}, - {name = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}}, - {name = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl",hashes = {sha256 = "0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}}, - {name = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}}, - {name = "markupsafe-3.0.3-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl",hashes = {sha256 = "729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}}, - {name = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl",hashes = {sha256 = "bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}}, - {name = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl",hashes = {sha256 = "5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl",hashes = {sha256 = "915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}}, - {name = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}}, - {name = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}}, - {name = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}}, - {name = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}}, - {name = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}}, - {name = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}}, - {name = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}}, - {name = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl",hashes = {sha256 = "795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}}, - {name = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}}, - {name = "markupsafe-3.0.3-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl",hashes = {sha256 = "bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}}, - {name = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}}, - {name = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl",hashes = {sha256 = "7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl",hashes = {sha256 = "69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}}, - {name = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}}, - {name = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}}, - {name = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}}, - {name = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}}, - {name = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}}, - {name = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}}, - {name = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}}, - {name = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl",hashes = {sha256 = "83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}}, - {name = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}}, - {name = "markupsafe-3.0.3-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl",hashes = {sha256 = "d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}}, - {name = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}}, - {name = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl",hashes = {sha256 = "35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}}, - {name = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}}, - {name = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}}, - {name = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}}, - {name = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}}, - {name = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}}, - {name = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}}, - {name = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl",hashes = {sha256 = "7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}}, - {name = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}}, - {name = "markupsafe-3.0.3-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl",hashes = {sha256 = "0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}}, - {name = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl",hashes = {sha256 = "de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}}, - {name = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl",hashes = {sha256 = "3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "matplotlib" -version = "3.10.8" -requires-python = ">=3.10" -sdist = {name = "matplotlib-3.10.8.tar.gz", url = "https://files.pythonhosted.org/packages/8a/76/d3c6e3a13fe484ebe7718d14e269c9569c4eb0020a968a327acb3b9a8fe6/matplotlib-3.10.8.tar.gz", hashes = {sha256 = "2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3"}} -wheels = [ - {name = "matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/3c/43/9c0ff7a2f11615e516c3b058e1e6e8f9614ddeca53faca06da267c48345d/matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f"}}, - {name = "matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/6f/ca/e8ae28649fcdf039fda5ef554b40a95f50592a3c47e6f7270c9561c12b07/matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b"}}, - {name = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/f1/6f/009d129ae70b75e88cbe7e503a12a4c0670e08ed748a902c2568909e9eb5/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d"}}, - {name = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/f5/26/4221a741eb97967bc1fd5e4c52b9aa5a91b2f4ec05b59f6def4d820f9df9/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008"}}, - {name = "matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/1f/f3/3abf75f38605772cf48a9daf5821cd4f563472f38b4b828c6fba6fa6d06e/matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c"}}, - {name = "matplotlib-3.10.8-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/93/a5/de89ac80f10b8dc615807ee1133cd99ac74082581196d4d9590bea10690d/matplotlib-3.10.8-cp314-cp314-win_amd64.whl",hashes = {sha256 = "83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11"}}, - {name = "matplotlib-3.10.8-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/69/ce/b006495c19ccc0a137b48083168a37bd056392dee02f87dba0472f2797fe/matplotlib-3.10.8-cp314-cp314-win_arm64.whl",hashes = {sha256 = "2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8"}}, - {name = "matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/68/d9/b31116a3a855bd313c6fcdb7226926d59b041f26061c6c5b1be66a08c826/matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50"}}, - {name = "matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/1e/90/6effe8103f0272685767ba5f094f453784057072f49b393e3ea178fe70a5/matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908"}}, - {name = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/d7/65/a73188711bea603615fc0baecca1061429ac16940e2385433cc778a9d8e7/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a"}}, - {name = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/f4/3d/b5c5d5d5be8ce63292567f0e2c43dde9953d3ed86ac2de0a72e93c8f07a1/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1"}}, - {name = "matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/4d/4b/e7beb6bbd49f6bae727a12b270a2654d13c397576d25bd6786e47033300f/matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c"}}, - {name = "matplotlib-3.10.8-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/7c/e6/76f2813d31f032e65f6f797e3f2f6e4aab95b65015924b1c51370395c28a/matplotlib-3.10.8-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b"}}, - {name = "matplotlib-3.10.8-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f"}}, - {name = "matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/3d/b9/15fd5541ef4f5b9a17eefd379356cf12175fe577424e7b1d80676516031a/matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6"}}, - {name = "matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1"}}, - {name = "matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486"}}, - {name = "matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce"}}, - {name = "matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/5d/7c/8dc289776eae5109e268c4fb92baf870678dc048a25d4ac903683b86d5bf/matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6"}}, - {name = "matplotlib-3.10.8-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/64/40/37612487cc8a437d4dd261b32ca21fe2d79510fe74af74e1f42becb1bdb8/matplotlib-3.10.8-cp313-cp313-win_amd64.whl",hashes = {sha256 = "e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149"}}, - {name = "matplotlib-3.10.8-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/66/52/8d8a8730e968185514680c2a6625943f70269509c3dcfc0dcf7d75928cb8/matplotlib-3.10.8-cp313-cp313-win_arm64.whl",hashes = {sha256 = "c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645"}}, - {name = "matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/b5/27/51fe26e1062f298af5ef66343d8ef460e090a27fea73036c76c35821df04/matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077"}}, - {name = "matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/2c/1e/4de865bc591ac8e3062e835f42dd7fe7a93168d519557837f0e37513f629/matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22"}}, - {name = "matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/c6/cb/2f7b6e75fb4dce87ef91f60cac4f6e34f4c145ab036a22318ec837971300/matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39"}}, - {name = "matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/46/b3/bd9c57d6ba670a37ab31fb87ec3e8691b947134b201f881665b28cc039ff/matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565"}}, - {name = "matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c0/3d/8b94a481456dfc9dfe6e39e93b5ab376e50998cddfd23f4ae3b431708f16/matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a"}}, - {name = "matplotlib-3.10.8-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bd/cd/bc06149fe5585ba800b189a6a654a75f1f127e8aab02fd2be10df7fa500c/matplotlib-3.10.8-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958"}}, - {name = "matplotlib-3.10.8-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/e3/de/b22cf255abec916562cc04eef457c13e58a1990048de0c0c3604d082355e/matplotlib-3.10.8-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5"}}, - {name = "matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/9e/67/f997cdcbb514012eb0d10cd2b4b332667997fb5ebe26b8d41d04962fa0e6/matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "64fcc24778ca0404ce0cb7b6b77ae1f4c7231cdd60e6778f999ee05cbd581b9a"}}, - {name = "matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7e/65/07d5f5c7f7c994f12c768708bd2e17a4f01a2b0f44a1c9eccad872433e2e/matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "b9a5ca4ac220a0cdd1ba6bcba3608547117d30468fefce49bb26f55c1a3d5c58"}}, - {name = "matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/3e/f3/c5195b1ae57ef85339fd7285dfb603b22c8b4e79114bae5f4f0fcf688677/matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "3ab4aabc72de4ff77b3ec33a6d78a68227bf1123465887f9905ba79184a1cc04"}}, - {name = "matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/00/f9/7638f5cc82ec8a7aa005de48622eecc3ed7c9854b96ba15bd76b7fd27574/matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "24d50994d8c5816ddc35411e50a86ab05f575e2530c02752e02538122613371f"}}, - {name = "matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/57/61/78cd5920d35b29fd2a0fe894de8adf672ff52939d2e9b43cb83cd5ce1bc7/matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "99eefd13c0dc3b3c1b4d561c1169e65fe47aab7b8158754d7c084088e2329466"}}, - {name = "matplotlib-3.10.8-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/30/4e/c10f171b6e2f44d9e3a2b96efa38b1677439d79c99357600a62cc1e9594e/matplotlib-3.10.8-cp312-cp312-win_amd64.whl",hashes = {sha256 = "dd80ecb295460a5d9d260df63c43f4afbdd832d725a531f008dad1664f458adf"}}, - {name = "matplotlib-3.10.8-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f1/76/934db220026b5fef85f45d51a738b91dea7d70207581063cd9bd8fafcf74/matplotlib-3.10.8-cp312-cp312-win_arm64.whl",hashes = {sha256 = "3c624e43ed56313651bc18a47f838b60d7b8032ed348911c54906b130b20071b"}}, - {name = "matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/f8/86/de7e3a1cdcfc941483af70609edc06b83e7c8a0e0dc9ac325200a3f4d220/matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl",hashes = {sha256 = "6be43b667360fef5c754dda5d25a32e6307a03c204f3c0fc5468b78fa87b4160"}}, - {name = "matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/fd/14/baad3222f424b19ce6ad243c71de1ad9ec6b2e4eb1e458a48fdc6d120401/matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "a2b336e2d91a3d7006864e0990c83b216fcdca64b5a6484912902cef87313d78"}}, - {name = "matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/8f/a0/7024215e95d456de5883e6732e708d8187d9753a21d32f8ddb3befc0c445/matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "efb30e3baaea72ce5928e32bab719ab4770099079d66726a62b11b1ef7273be4"}}, - {name = "matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/5a/f4/b8347351da9a5b3f41e26cf547252d861f685c6867d179a7c9d60ad50189/matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "d56a1efd5bfd61486c8bc968fa18734464556f0fb8e51690f4ac25d85cbbbbc2"}}, - {name = "matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/9e/c0/c7b914e297efe0bc36917bf216b2acb91044b91e930e878ae12981e461e5/matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "238b7ce5717600615c895050239ec955d91f321c209dd110db988500558e70d6"}}, - {name = "matplotlib-3.10.8-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6f/d3/a4bbc01c237ab710a1f22b4da72f4ff6d77eb4c7735ea9811a94ae239067/matplotlib-3.10.8-cp311-cp311-win_amd64.whl",hashes = {sha256 = "18821ace09c763ec93aef5eeff087ee493a24051936d7b9ebcad9662f66501f9"}}, - {name = "matplotlib-3.10.8-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/89/dd/a0b6588f102beab33ca6f5218b31725216577b2a24172f327eaf6417d5c9/matplotlib-3.10.8-cp311-cp311-win_arm64.whl",hashes = {sha256 = "bab485bcf8b1c7d2060b4fcb6fc368a9e6f4cd754c9c2fea281f4be21df394a2"}}, - {name = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/04/30/3afaa31c757f34b7725ab9d2ba8b48b5e89c2019c003e7d0ead143aabc5a/matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1"}}, - {name = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/48/2f/6334aec331f57485a642a7c8be03cb286f29111ae71c46c38b363230063c/matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a"}}, - {name = "matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/e4/6d6f14b2a759c622f191b2d67e9075a3f56aaccb3be4bb9bb6890030d0a0/matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "contourpy>=1.0.1", - "cycler>=0.10", - "fonttools>=4.22.0", - "kiwisolver>=1.3.1", - "numpy>=1.23", - "packaging>=20.0", - "pillow>=8", - "pyparsing>=3", - "python-dateutil>=2.7", -] - -[[packages]] -name = "matplotlib-inline" -version = "0.2.1" -requires-python = ">=3.9" -sdist = {name = "matplotlib_inline-0.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hashes = {sha256 = "e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe"}} -wheels = [ - {name = "matplotlib_inline-0.2.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl",hashes = {sha256 = "d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "traitlets", -] - -[[packages]] -name = "mccabe" -version = "0.7.0" -requires-python = ">=3.6" -sdist = {name = "mccabe-0.7.0.tar.gz", url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hashes = {sha256 = "348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}} -wheels = [ - {name = "mccabe-0.7.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl",hashes = {sha256 = "6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "mdit-py-plugins" -version = "0.5.0" -requires-python = ">=3.10" -sdist = {name = "mdit_py_plugins-0.5.0.tar.gz", url = "https://files.pythonhosted.org/packages/b2/fd/a756d36c0bfba5f6e39a1cdbdbfdd448dc02692467d83816dff4592a1ebc/mdit_py_plugins-0.5.0.tar.gz", hashes = {sha256 = "f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6"}} -wheels = [ - {name = "mdit_py_plugins-0.5.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl",hashes = {sha256 = "07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "markdown-it-py<5.0.0,>=2.0.0", -] - -[[packages]] -name = "mdurl" -version = "0.1.2" -requires-python = ">=3.7" -sdist = {name = "mdurl-0.1.2.tar.gz", url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hashes = {sha256 = "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}} -wheels = [ - {name = "mdurl-0.1.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl",hashes = {sha256 = "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "mistune" -version = "3.2.0" -requires-python = ">=3.8" -sdist = {name = "mistune-3.2.0.tar.gz", url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hashes = {sha256 = "708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a"}} -wheels = [ - {name = "mistune-3.2.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl",hashes = {sha256 = "febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "typing-extensions; python_version < \"3.11\"", -] - -[[packages]] -name = "myst-parser" -version = "5.0.0" -requires-python = ">=3.11" -sdist = {name = "myst_parser-5.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/33/fa/7b45eef11b7971f0beb29d27b7bfe0d747d063aa29e170d9edd004733c8a/myst_parser-5.0.0.tar.gz", hashes = {sha256 = "f6f231452c56e8baa662cc352c548158f6a16fcbd6e3800fc594978002b94f3a"}} -wheels = [ - {name = "myst_parser-5.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d3/ac/686789b9145413f1a61878c407210e41bfdb097976864e0913078b24098c/myst_parser-5.0.0-py3-none-any.whl",hashes = {sha256 = "ab31e516024918296e169139072b81592336f2fef55b8986aa31c9f04b5f7211"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "docutils<0.23,>=0.20", - "jinja2", - "markdown-it-py~=4.0", - "mdit-py-plugins~=0.5", - "pyyaml", - "sphinx<10,>=8", -] - -[[packages]] -name = "narwhals" -version = "2.19.0" -requires-python = ">=3.9" -sdist = {name = "narwhals-2.19.0.tar.gz", url = "https://files.pythonhosted.org/packages/4e/1a/bd3317c0bdbcd9ffb710ddf5250b32898f8f2c240be99494fe137feb77a7/narwhals-2.19.0.tar.gz", hashes = {sha256 = "14fd7040b5ff211d415a82e4827b9d04c354e213e72a6d0730205ffd72e3b7ff"}} -wheels = [ - {name = "narwhals-2.19.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/37/72/e61e3091e0e00fae9d3a8ef85ece9d2cd4b5966058e1f2901ce42679eebf/narwhals-2.19.0-py3-none-any.whl",hashes = {sha256 = "1f8dfa4a33a6dbff878c3e9be4c3b455dfcaf2a9322f1357db00e4e92e95b84b"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "nb2plots" -version = "0.7.2" -requires-python = ">=3.7" -sdist = {name = "nb2plots-0.7.2.tar.gz", url = "https://files.pythonhosted.org/packages/47/1c/56467472e0dd8824f21d55ef2f38f245d1d60667e05995aa28a8a953380d/nb2plots-0.7.2.tar.gz", hashes = {sha256 = "4f0de757fce4d4f6937ebfa2ffbabb7feb87134c61c944055e95a1999aab2d8b"}} -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "ipython[notebook]>=7.16.3", - "matplotlib>=3.2", - "nbconvert>=6.0.7", - "numpy>=1.20", - "sphinx>=4", - "sphinxtesters>=0.2.3", - "texext>=0.6.6", -] - -[[packages]] -name = "nbclient" -version = "0.10.4" -requires-python = ">=3.10.0" -sdist = {name = "nbclient-0.10.4.tar.gz", url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hashes = {sha256 = "1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9"}} -wheels = [ - {name = "nbclient-0.10.4-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl",hashes = {sha256 = "9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "jupyter-client>=6.1.12", - "jupyter-core!=5.0.*,>=4.12", - "nbformat>=5.1.3", - "traitlets>=5.4", -] - -[[packages]] -name = "nbconvert" -version = "7.17.1" -requires-python = ">=3.9" -sdist = {name = "nbconvert-7.17.1.tar.gz", url = "https://files.pythonhosted.org/packages/01/b1/708e53fe2e429c103c6e6e159106bcf0357ac41aa4c28772bd8402339051/nbconvert-7.17.1.tar.gz", hashes = {sha256 = "34d0d0a7e73ce3cbab6c5aae8f4f468797280b01fd8bd2ca746da8569eddd7d2"}} -wheels = [ - {name = "nbconvert-7.17.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/67/f8/bb0a9d5f46819c821dc1f004aa2cc29b1d91453297dbf5ff20470f00f193/nbconvert-7.17.1-py3-none-any.whl",hashes = {sha256 = "aa85c087b435e7bf1ffd03319f658e285f2b89eccab33bc1ba7025495ab3e7c8"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "beautifulsoup4", - "bleach[css]!=5.0.0", - "defusedxml", - "importlib-metadata>=3.6; python_version < \"3.10\"", - "jinja2>=3.0", - "jupyter-core>=4.7", - "jupyterlab-pygments", - "markupsafe>=2.0", - "mistune<4,>=2.0.3", - "nbclient>=0.5.0", - "nbformat>=5.7", - "packaging", - "pandocfilters>=1.4.1", - "pygments>=2.4.1", - "traitlets>=5.1", -] - -[[packages]] -name = "nbformat" -version = "5.10.4" -requires-python = ">=3.8" -sdist = {name = "nbformat-5.10.4.tar.gz", url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hashes = {sha256 = "322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"}} -wheels = [ - {name = "nbformat-5.10.4-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl",hashes = {sha256 = "3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "fastjsonschema>=2.15", - "jsonschema>=2.6", - "jupyter-core!=5.0.*,>=4.12", - "traitlets>=5.1", -] - -[[packages]] -name = "nest-asyncio" -version = "1.6.0" -requires-python = ">=3.5" -sdist = {name = "nest_asyncio-1.6.0.tar.gz", url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hashes = {sha256 = "6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}} -wheels = [ - {name = "nest_asyncio-1.6.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl",hashes = {sha256 = "87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "nodeenv" -version = "1.10.0" -requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -sdist = {name = "nodeenv-1.10.0.tar.gz", url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hashes = {sha256 = "996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb"}} -wheels = [ - {name = "nodeenv-1.10.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl",hashes = {sha256 = "5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827"}}, -] -marker = "\"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "numpy" -version = "1.26.4" -requires-python = ">=3.9" -sdist = {name = "numpy-1.26.4.tar.gz", url = "https://files.pythonhosted.org/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-1.26.4.tar.gz", hashes = {sha256 = "2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}} -wheels = [ - {name = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/95/12/8f2020a8e8b8383ac0177dc9570aad031a3beb12e38847f7129bacd96228/numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl",hashes = {sha256 = "b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}}, - {name = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/75/5b/ca6c8bd14007e5ca171c7c03102d17b4f4e0ceb53957e8c44343a9546dcc/numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}}, - {name = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/79/f8/97f10e6755e2a7d027ca783f63044d5b1bc1ae7acb12afe6a9b4286eac17/numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}}, - {name = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/0f/50/de23fde84e45f5c4fda2488c759b69990fd4512387a8632860f3ac9cd225/numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}}, - {name = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/4c/0c/9c603826b6465e82591e05ca230dfc13376da512b25ccd0894709b054ed0/numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl",hashes = {sha256 = "ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}}, - {name = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/76/8c/2ba3902e1a0fc1c74962ea9bb33a534bb05984ad7ff9515bf8d07527cadd/numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl",hashes = {sha256 = "1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}}, - {name = "numpy-1.26.4-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/28/4a/46d9e65106879492374999e76eb85f87b15328e06bd1550668f79f7b18c6/numpy-1.26.4-cp312-cp312-win32.whl",hashes = {sha256 = "50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}}, - {name = "numpy-1.26.4-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/16/2e/86f24451c2d530c88daf997cb8d6ac622c1d40d19f5a031ed68a4b73a374/numpy-1.26.4-cp312-cp312-win_amd64.whl",hashes = {sha256 = "08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}}, - {name = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}}, - {name = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}}, - {name = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/79/ae/7e5b85136806f9dadf4878bf73cf223fe5c2636818ba3ab1c585d0403164/numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}}, - {name = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}}, - {name = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/09/bf/2b1aaf8f525f2923ff6cfcf134ae5e750e279ac65ebf386c75a0cf6da06a/numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl",hashes = {sha256 = "96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}}, - {name = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/df/a0/4e0f14d847cfc2a633a1c8621d00724f3206cfeddeb66d35698c4e2cf3d2/numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}}, - {name = "numpy-1.26.4-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/d2/b7/a734c733286e10a7f1a8ad1ae8c90f2d33bf604a96548e0a4a3a6739b468/numpy-1.26.4-cp311-cp311-win32.whl",hashes = {sha256 = "1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}}, - {name = "numpy-1.26.4-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl",hashes = {sha256 = "cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "numpydoc" -version = "1.10.0" -requires-python = ">=3.10" -sdist = {name = "numpydoc-1.10.0.tar.gz", url = "https://files.pythonhosted.org/packages/e9/3c/dfccc9e7dee357fb2aa13c3890d952a370dd0ed071e0f7ed62ed0df567c1/numpydoc-1.10.0.tar.gz", hashes = {sha256 = "3f7970f6eee30912260a6b31ac72bba2432830cd6722569ec17ee8d3ef5ffa01"}} -wheels = [ - {name = "numpydoc-1.10.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/62/5e/3a6a3e90f35cea3853c45e5d5fb9b7192ce4384616f932cf7591298ab6e1/numpydoc-1.10.0-py3-none-any.whl",hashes = {sha256 = "3149da9874af890bcc2a82ef7aae5484e5aa81cb2778f08e3c307ba6d963721b"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "sphinx>=6", - "tomli>=1.1.0; python_version < \"3.11\"", -] - -[[packages]] -name = "packaging" -version = "26.1" -requires-python = ">=3.8" -sdist = {name = "packaging-26.1.tar.gz", url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hashes = {sha256 = "f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de"}} -wheels = [ - {name = "packaging-26.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl",hashes = {sha256 = "5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras or \"test\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pandas" -version = "2.2.1" -requires-python = ">=3.9" -sdist = {name = "pandas-2.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/3d/59/2afa81b9fb300c90531803c0fd43ff4548074fa3e8d0f747ef63b3b5e77a/pandas-2.2.1.tar.gz", hashes = {sha256 = "0ab90f87093c13f3e8fa45b48ba9f39181046e8f3317d3aadb2fffbb1b978572"}} -wheels = [ - {name = "pandas-2.2.1-cp312-cp312-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/ed/b9/660353ce2b1bd5b6e0f5c992836d91909c0da1ccb59c16565ad0a37e839d/pandas-2.2.1-cp312-cp312-macosx_10_9_x86_64.whl",hashes = {sha256 = "88ecb5c01bb9ca927ebc4098136038519aa5d66b44671861ffab754cae75102c"}}, - {name = "pandas-2.2.1-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/19/4e/6a7f400d4b65f82e37eefa7dbbe3e6f0a4fa542ca7ebb68c787eeebdc497/pandas-2.2.1-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "04f6ec3baec203c13e3f8b139fb0f9f86cd8c0b94603ae3ae8ce9a422e9f5bee"}}, - {name = "pandas-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/d7/2b/3e00e92a6b430313da68b15e925c6dba05f672d716cf3b02bcd3d0381974/pandas-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "a935a90a76c44fe170d01e90a3594beef9e9a6220021acfb26053d01426f7dc2"}}, - {name = "pandas-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/78/f4/19f1dda9ab1eaa38301e445925f92b303d415d4c4115e56c0d62774421f7/pandas-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "c391f594aae2fd9f679d419e9a4d5ba4bce5bb13f6a989195656e7dc4b95c8f0"}}, - {name = "pandas-2.2.1-cp312-cp312-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/6f/cd/8b84912b5bfab19b1fcea2f732d2e3a2d134d558f141e9dffa5dbfd9d23b/pandas-2.2.1-cp312-cp312-musllinux_1_1_aarch64.whl",hashes = {sha256 = "9d1265545f579edf3f8f0cb6f89f234f5e44ba725a34d86535b1a1d38decbccc"}}, - {name = "pandas-2.2.1-cp312-cp312-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/11/e7/65bf50aff86da6554cdffdcd87ced857c79a29dfaf1d85fdf97955d76d02/pandas-2.2.1-cp312-cp312-musllinux_1_1_x86_64.whl",hashes = {sha256 = "11940e9e3056576ac3244baef2fedade891977bcc1cb7e5cc8f8cc7d603edc89"}}, - {name = "pandas-2.2.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/71/00/6beaeeba7f075d15ea167a5caa039b861e58ff2f58a5b659abb9b544c8f6/pandas-2.2.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "4acf681325ee1c7f950d058b05a820441075b0dd9a2adf5c4835b9bc056bf4fb"}}, - {name = "pandas-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/f1/8b/617792ad1feef330e87d7459584a1f91aa8aea373d8b168ac5d24fddd808/pandas-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "f821213d48f4ab353d20ebc24e4faf94ba40d76680642fb7ce2ea31a3ad94f9b"}}, - {name = "pandas-2.2.1-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a5/78/1d859bfb619c067e3353ed079248ae9532c105c4e018fa9a776d04b34572/pandas-2.2.1-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "c70e00c2d894cb230e5c15e4b1e1e6b2b478e09cf27cc593a11ef955b9ecc81a"}}, - {name = "pandas-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/91/bf/8c57707e440f944ba2cf3d6f6ae6c29883fac20fbe5d2ad485229149f273/pandas-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "e97fbb5387c69209f134893abc788a6486dbf2f9e511070ca05eed4b930b1b02"}}, - {name = "pandas-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d4/47/1ccf9f62d2674d3ca3e95452c5f9dd114234d1535dec77c96528bf6a31fc/pandas-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "101d0eb9c5361aa0146f500773395a03839a5e6ecde4d4b6ced88b7e5a1a6403"}}, - {name = "pandas-2.2.1-cp311-cp311-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/e3/da/9522ba4b32b20a344c37a970d7835d261df1427d943e02d48820253833ee/pandas-2.2.1-cp311-cp311-musllinux_1_1_aarch64.whl",hashes = {sha256 = "7d2ed41c319c9fb4fd454fe25372028dfa417aacb9790f68171b2e3f06eae8cd"}}, - {name = "pandas-2.2.1-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/e0/c3/da6ffa0d3d510c378f6e46496cf7f84f35e15836d0de4e9880f40247eb60/pandas-2.2.1-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "af5d3c00557d657c8773ef9ee702c61dd13b9d7426794c9dfeb1dc4a0bf0ebc7"}}, - {name = "pandas-2.2.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/61/11/1812ef6cbd7433ad240f72161ce5f84c4c450cede4db080365d371d29117/pandas-2.2.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "06cf591dbaefb6da9de8472535b185cba556d0ce2e6ed28e21d919704fef1a9e"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "numpy<2,>=1.22.4; python_version < \"3.11\"", - "numpy<2,>=1.23.2; python_version == \"3.11\"", - "numpy<2,>=1.26.0; python_version >= \"3.12\"", - "python-dateutil>=2.8.2", - "pytz>=2020.1", - "tzdata>=2022.7", -] - -[[packages]] -name = "pandocfilters" -version = "1.5.1" -requires-python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -sdist = {name = "pandocfilters-1.5.1.tar.gz", url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hashes = {sha256 = "002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}} -wheels = [ - {name = "pandocfilters-1.5.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl",hashes = {sha256 = "93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "parso" -version = "0.8.6" -requires-python = ">=3.6" -sdist = {name = "parso-0.8.6.tar.gz", url = "https://files.pythonhosted.org/packages/81/76/a1e769043c0c0c9fe391b702539d594731a4362334cdf4dc25d0c09761e7/parso-0.8.6.tar.gz", hashes = {sha256 = "2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd"}} -wheels = [ - {name = "parso-0.8.6-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b6/61/fae042894f4296ec49e3f193aff5d7c18440da9e48102c3315e1bc4519a7/parso-0.8.6-py2.py3-none-any.whl",hashes = {sha256 = "2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "patsy" -version = "1.0.2" -requires-python = ">=3.6" -sdist = {name = "patsy-1.0.2.tar.gz", url = "https://files.pythonhosted.org/packages/be/44/ed13eccdd0519eff265f44b670d46fbb0ec813e2274932dc1c0e48520f7d/patsy-1.0.2.tar.gz", hashes = {sha256 = "cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0"}} -wheels = [ - {name = "patsy-1.0.2-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl",hashes = {sha256 = "37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "numpy>=1.4", -] - -[[packages]] -name = "pexpect" -version = "4.9.0" -sdist = {name = "pexpect-4.9.0.tar.gz", url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hashes = {sha256 = "ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}} -wheels = [ - {name = "pexpect-4.9.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl",hashes = {sha256 = "7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}}, -] -marker = "(sys_platform != \"win32\" and sys_platform != \"emscripten\") and \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "ptyprocess>=0.5", -] - -[[packages]] -name = "pillow" -version = "12.2.0" -requires-python = ">=3.10" -sdist = {name = "pillow-12.2.0.tar.gz", url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hashes = {sha256 = "a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5"}} -wheels = [ - {name = "pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl",url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl",hashes = {sha256 = "3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8"}}, - {name = "pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl",url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl",hashes = {sha256 = "6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b"}}, - {name = "pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl",url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl",hashes = {sha256 = "6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295"}}, - {name = "pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl",hashes = {sha256 = "2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed"}}, - {name = "pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae"}}, - {name = "pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601"}}, - {name = "pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be"}}, - {name = "pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f"}}, - {name = "pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286"}}, - {name = "pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50"}}, - {name = "pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104"}}, - {name = "pillow-12.2.0-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl",hashes = {sha256 = "632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7"}}, - {name = "pillow-12.2.0-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl",hashes = {sha256 = "4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150"}}, - {name = "pillow-12.2.0-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl",hashes = {sha256 = "b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1"}}, - {name = "pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463"}}, - {name = "pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3"}}, - {name = "pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166"}}, - {name = "pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe"}}, - {name = "pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd"}}, - {name = "pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e"}}, - {name = "pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06"}}, - {name = "pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43"}}, - {name = "pillow-12.2.0-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl",hashes = {sha256 = "6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354"}}, - {name = "pillow-12.2.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1"}}, - {name = "pillow-12.2.0-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb"}}, - {name = "pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl",url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl",hashes = {sha256 = "8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c"}}, - {name = "pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl",url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl",hashes = {sha256 = "50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2"}}, - {name = "pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl",url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl",hashes = {sha256 = "766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c"}}, - {name = "pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795"}}, - {name = "pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f"}}, - {name = "pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed"}}, - {name = "pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9"}}, - {name = "pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed"}}, - {name = "pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3"}}, - {name = "pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9"}}, - {name = "pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795"}}, - {name = "pillow-12.2.0-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl",hashes = {sha256 = "144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e"}}, - {name = "pillow-12.2.0-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl",hashes = {sha256 = "390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b"}}, - {name = "pillow-12.2.0-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl",hashes = {sha256 = "8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06"}}, - {name = "pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b"}}, - {name = "pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f"}}, - {name = "pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612"}}, - {name = "pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c"}}, - {name = "pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea"}}, - {name = "pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4"}}, - {name = "pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4"}}, - {name = "pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea"}}, - {name = "pillow-12.2.0-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl",hashes = {sha256 = "ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24"}}, - {name = "pillow-12.2.0-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98"}}, - {name = "pillow-12.2.0-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453"}}, - {name = "pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5"}}, - {name = "pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421"}}, - {name = "pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987"}}, - {name = "pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76"}}, - {name = "pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005"}}, - {name = "pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780"}}, - {name = "pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5"}}, - {name = "pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5"}}, - {name = "pillow-12.2.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl",hashes = {sha256 = "58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940"}}, - {name = "pillow-12.2.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5"}}, - {name = "pillow-12.2.0-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl",hashes = {sha256 = "af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414"}}, - {name = "pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl",url = "https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl",hashes = {sha256 = "8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab"}}, - {name = "pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/47/a1/d5ff69e747374c33a3b53b9f98cca7889fce1fd03d79cdc4e1bccc6c5a87/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65"}}, - {name = "pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/df/21/e3fbdf54408a973c7f7f89a23b2cb97a7ef30c61ab4142af31eee6aebc88/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7"}}, - {name = "pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/d3/f1/00b7278c7dd52b17ad4329153748f87b6756ec195ff786c2bdf12518337d/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e"}}, - {name = "pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ad/cf/220a5994ef1b10e70e85748b75649d77d506499352be135a4989c957b701/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705"}}, - {name = "pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176"}}, - {name = "pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/6b/3d/45132c57d5fb4b5744567c3817026480ac7fc3ce5d4c47902bc0e7f6f853/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b"}}, - {name = "pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/7d/2e/9df2fc1e82097b1df3dce58dc43286aa01068e918c07574711fcc53e6fb4/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909"}}, - {name = "pillow-12.2.0-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/bd/2e/2941e42858ebb67e50ae741473de81c2984e6eff7b397017623c676e2e8d/pillow-12.2.0-cp311-cp311-win32.whl",hashes = {sha256 = "8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808"}}, - {name = "pillow-12.2.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60"}}, - {name = "pillow-12.2.0-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/c2/88/549194b5d6f1f494b485e493edc6693c0a16f4ada488e5bd974ed1f42fad/pillow-12.2.0-cp311-cp311-win_arm64.whl",hashes = {sha256 = "9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe"}}, - {name = "pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f"}}, - {name = "pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d"}}, - {name = "pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f"}}, - {name = "pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",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",hashes = {sha256 = "0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e"}}, - {name = "pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0"}}, - {name = "pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1"}}, - {name = "pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl",hashes = {sha256 = "bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "platformdirs" -version = "4.9.6" -requires-python = ">=3.10" -sdist = {name = "platformdirs-4.9.6.tar.gz", url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hashes = {sha256 = "3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a"}} -wheels = [ - {name = "platformdirs-4.9.6-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl",hashes = {sha256 = "e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917"}}, -] -marker = "\"docs\" in extras or \"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "plotly" -version = "6.1.1" -requires-python = ">=3.8" -sdist = {name = "plotly-6.1.1.tar.gz", url = "https://files.pythonhosted.org/packages/8a/7c/f396bc817975252afbe7af102ce09cd12ac40a8e90b8699a857d1b15c8a3/plotly-6.1.1.tar.gz", hashes = {sha256 = "84a4f3d36655f1328fa3155377c7e8a9533196697d5b79a4bc5e905bdd09a433"}} -wheels = [ - {name = "plotly-6.1.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/75/f3/f8cb7066f761e2530e1280889e3413769891e349fca35ee7290e4ace35f5/plotly-6.1.1-py3-none-any.whl",hashes = {sha256 = "9cca7167406ebf7ff541422738402159ec3621a608ff7b3e2f025573a1c76225"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "narwhals>=1.15.1", - "packaging", -] - -[[packages]] -name = "pluggy" -version = "1.6.0" -requires-python = ">=3.9" -sdist = {name = "pluggy-1.6.0.tar.gz", url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hashes = {sha256 = "7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}} -wheels = [ - {name = "pluggy-1.6.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl",hashes = {sha256 = "e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}}, -] -marker = "\"test\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pre-commit" -version = "4.5.1" -requires-python = ">=3.10" -sdist = {name = "pre_commit-4.5.1.tar.gz", url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hashes = {sha256 = "eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61"}} -wheels = [ - {name = "pre_commit-4.5.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl",hashes = {sha256 = "3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77"}}, -] -marker = "\"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [ - "cfgv>=2.0.0", - "identify>=1.0.0", - "nodeenv>=0.11.1", - "pyyaml>=5.1", - "virtualenv>=20.10.0", -] - -[[packages]] -name = "prompt-toolkit" -version = "3.0.52" -requires-python = ">=3.8" -sdist = {name = "prompt_toolkit-3.0.52.tar.gz", url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hashes = {sha256 = "28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855"}} -wheels = [ - {name = "prompt_toolkit-3.0.52-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl",hashes = {sha256 = "9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "wcwidth", -] - -[[packages]] -name = "psutil" -version = "7.2.2" -requires-python = ">=3.6" -sdist = {name = "psutil-7.2.2.tar.gz", url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hashes = {sha256 = "0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372"}} -wheels = [ - {name = "psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00"}}, - {name = "psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9"}}, - {name = "psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a"}}, - {name = "psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf"}}, - {name = "psutil-7.2.2-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1"}}, - {name = "psutil-7.2.2-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841"}}, - {name = "psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b"}}, - {name = "psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea"}}, - {name = "psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63"}}, - {name = "psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312"}}, - {name = "psutil-7.2.2-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b"}}, - {name = "psutil-7.2.2-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9"}}, - {name = "psutil-7.2.2-cp37-abi3-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl",hashes = {sha256 = "eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988"}}, - {name = "psutil-7.2.2-cp37-abi3-win_arm64.whl",url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl",hashes = {sha256 = "8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee"}}, - {name = "psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl",hashes = {sha256 = "ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486"}}, - {name = "psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl",hashes = {sha256 = "1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979"}}, - {name = "psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9"}}, - {name = "psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e"}}, - {name = "psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl",hashes = {sha256 = "fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8"}}, - {name = "psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl",hashes = {sha256 = "b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "ptyprocess" -version = "0.7.0" -sdist = {name = "ptyprocess-0.7.0.tar.gz", url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hashes = {sha256 = "5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}} -wheels = [ - {name = "ptyprocess-0.7.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl",hashes = {sha256 = "4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}}, -] -marker = "(sys_platform != \"win32\" and sys_platform != \"emscripten\") and \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pure-eval" -version = "0.2.3" -sdist = {name = "pure_eval-0.2.3.tar.gz", url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hashes = {sha256 = "5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}} -wheels = [ - {name = "pure_eval-0.2.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl",hashes = {sha256 = "1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pycparser" -version = "3.0" -requires-python = ">=3.10" -sdist = {name = "pycparser-3.0.tar.gz", url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hashes = {sha256 = "600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}} -wheels = [ - {name = "pycparser-3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl",hashes = {sha256 = "b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}}, -] -marker = "implementation_name == \"pypy\" and \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pygments" -version = "2.20.0" -requires-python = ">=3.9" -sdist = {name = "pygments-2.20.0.tar.gz", url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hashes = {sha256 = "6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}} -wheels = [ - {name = "pygments-2.20.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl",hashes = {sha256 = "81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}}, -] -marker = "\"docs\" in extras or \"test\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pylint" -version = "4.0.5" -requires-python = ">=3.10.0" -sdist = {name = "pylint-4.0.5.tar.gz", url = "https://files.pythonhosted.org/packages/e4/b6/74d9a8a68b8067efce8d07707fe6a236324ee1e7808d2eb3646ec8517c7d/pylint-4.0.5.tar.gz", hashes = {sha256 = "8cd6a618df75deb013bd7eb98327a95f02a6fb839205a6bbf5456ef96afb317c"}} -wheels = [ - {name = "pylint-4.0.5-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d5/6f/9ac2548e290764781f9e7e2aaf0685b086379dabfb29ca38536985471eaf/pylint-4.0.5-py3-none-any.whl",hashes = {sha256 = "00f51c9b14a3b3ae08cff6b2cdd43f28165c78b165b628692e428fb1f8dc2cf2"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "astroid<=4.1.dev0,>=4.0.2", - "colorama>=0.4.5; sys_platform == \"win32\"", - "dill>=0.2; python_version < \"3.11\"", - "dill>=0.3.6; python_version >= \"3.11\"", - "dill>=0.3.7; python_version >= \"3.12\"", - "isort!=5.13,<9,>=5", - "mccabe<0.8,>=0.6", - "platformdirs>=2.2", - "tomli>=1.1; python_version < \"3.11\"", - "tomlkit>=0.10.1", - "typing-extensions>=3.10; python_version < \"3.10\"", -] - -[[packages]] -name = "pyparsing" -version = "3.3.2" -requires-python = ">=3.9" -sdist = {name = "pyparsing-3.3.2.tar.gz", url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hashes = {sha256 = "c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc"}} -wheels = [ - {name = "pyparsing-3.3.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl",hashes = {sha256 = "850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pytest" -version = "9.0.3" -requires-python = ">=3.10" -sdist = {name = "pytest-9.0.3.tar.gz", url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hashes = {sha256 = "b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}} -wheels = [ - {name = "pytest-9.0.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl",hashes = {sha256 = "2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}}, -] -marker = "\"test\" in extras" - -[packages.tool.pdm] -dependencies = [ - "colorama>=0.4; sys_platform == \"win32\"", - "exceptiongroup>=1; python_version < \"3.11\"", - "iniconfig>=1.0.1", - "packaging>=22", - "pluggy<2,>=1.5", - "pygments>=2.7.2", - "tomli>=1; python_version < \"3.11\"", -] - -[[packages]] -name = "pytest-cov" -version = "7.1.0" -requires-python = ">=3.9" -sdist = {name = "pytest_cov-7.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hashes = {sha256 = "30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2"}} -wheels = [ - {name = "pytest_cov-7.1.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl",hashes = {sha256 = "a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678"}}, -] -marker = "\"test\" in extras" - -[packages.tool.pdm] -dependencies = [ - "coverage[toml]>=7.10.6", - "pluggy>=1.2", - "pytest>=7", -] - -[[packages]] -name = "python-dateutil" -version = "2.9.0.post0" -requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -sdist = {name = "python-dateutil-2.9.0.post0.tar.gz", url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hashes = {sha256 = "37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}} -wheels = [ - {name = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl",hashes = {sha256 = "a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "six>=1.5", -] - -[[packages]] -name = "python-discovery" -version = "1.2.2" -requires-python = ">=3.8" -sdist = {name = "python_discovery-1.2.2.tar.gz", url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hashes = {sha256 = "876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb"}} -wheels = [ - {name = "python_discovery-1.2.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl",hashes = {sha256 = "e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a"}}, -] -marker = "\"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [ - "filelock>=3.15.4", - "platformdirs<5,>=4.3.6", -] - -[[packages]] -name = "pytz" -version = "2026.1.post1" -sdist = {name = "pytz-2026.1.post1.tar.gz", url = "https://files.pythonhosted.org/packages/56/db/b8721d71d945e6a8ac63c0fc900b2067181dbb50805958d4d4661cf7d277/pytz-2026.1.post1.tar.gz", hashes = {sha256 = "3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1"}} -wheels = [ - {name = "pytz-2026.1.post1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl",hashes = {sha256 = "f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pyyaml" -version = "6.0.3" -requires-python = ">=3.8" -sdist = {name = "pyyaml-6.0.3.tar.gz", url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hashes = {sha256 = "d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}} -wheels = [ - {name = "pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac"}}, - {name = "pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310"}}, - {name = "pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7"}}, - {name = "pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788"}}, - {name = "pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5"}}, - {name = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764"}}, - {name = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35"}}, - {name = "pyyaml-6.0.3-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl",hashes = {sha256 = "4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac"}}, - {name = "pyyaml-6.0.3-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl",hashes = {sha256 = "93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9"}}, - {name = "pyyaml-6.0.3-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b"}}, - {name = "pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8"}}, - {name = "pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1"}}, - {name = "pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c"}}, - {name = "pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5"}}, - {name = "pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6"}}, - {name = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6"}}, - {name = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be"}}, - {name = "pyyaml-6.0.3-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl",hashes = {sha256 = "d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26"}}, - {name = "pyyaml-6.0.3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c"}}, - {name = "pyyaml-6.0.3-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl",hashes = {sha256 = "5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb"}}, - {name = "pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196"}}, - {name = "pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"}}, - {name = "pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28"}}, - {name = "pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c"}}, - {name = "pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"}}, - {name = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e"}}, - {name = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea"}}, - {name = "pyyaml-6.0.3-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl",hashes = {sha256 = "96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5"}}, - {name = "pyyaml-6.0.3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b"}}, - {name = "pyyaml-6.0.3-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl",hashes = {sha256 = "64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd"}}, - {name = "pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl",hashes = {sha256 = "44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e"}}, - {name = "pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824"}}, - {name = "pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c"}}, - {name = "pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",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",hashes = {sha256 = "850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00"}}, - {name = "pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d"}}, - {name = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a"}}, - {name = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4"}}, - {name = "pyyaml-6.0.3-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl",hashes = {sha256 = "8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}}, - {name = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl",hashes = {sha256 = "9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}}, -] -marker = "\"docs\" in extras or \"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "pyzmq" -version = "27.1.0" -requires-python = ">=3.8" -sdist = {name = "pyzmq-27.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hashes = {sha256 = "ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540"}} -wheels = [ - {name = "pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl",hashes = {sha256 = "ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl",url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl",hashes = {sha256 = "1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl",hashes = {sha256 = "544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl",hashes = {sha256 = "1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0"}}, - {name = "pyzmq-27.1.0-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7"}}, - {name = "pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl",url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl",hashes = {sha256 = "93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5"}}, - {name = "pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl",url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl",hashes = {sha256 = "fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl",hashes = {sha256 = "e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl",url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl",hashes = {sha256 = "08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl",hashes = {sha256 = "90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl",hashes = {sha256 = "7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2"}}, - {name = "pyzmq-27.1.0-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e"}}, - {name = "pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl",hashes = {sha256 = "452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc"}}, - {name = "pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl",url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl",hashes = {sha256 = "1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113"}}, - {name = "pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233"}}, - {name = "pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31"}}, - {name = "pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl",hashes = {sha256 = "0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28"}}, - {name = "pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl",hashes = {sha256 = "cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856"}}, - {name = "pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496"}}, - {name = "pyzmq-27.1.0-cp312-abi3-win32.whl",url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl",hashes = {sha256 = "250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd"}}, - {name = "pyzmq-27.1.0-cp312-abi3-win_amd64.whl",url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl",hashes = {sha256 = "9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf"}}, - {name = "pyzmq-27.1.0-cp312-abi3-win_arm64.whl",url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl",hashes = {sha256 = "75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f"}}, - {name = "pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl",hashes = {sha256 = "226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86"}}, - {name = "pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl",url = "https://files.pythonhosted.org/packages/bd/a0/fc7e78a23748ad5443ac3275943457e8452da67fda347e05260261108cbc/pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl",hashes = {sha256 = "0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581"}}, - {name = "pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/7e/22/37d15eb05f3bdfa4abea6f6d96eb3bb58585fbd3e4e0ded4e743bc650c97/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f"}}, - {name = "pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e"}}, - {name = "pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/cb/eb/bfdcb41d0db9cd233d6fb22dc131583774135505ada800ebf14dfb0a7c40/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e"}}, - {name = "pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/ab/21/e3180ca269ed4a0de5c34417dfe71a8ae80421198be83ee619a8a485b0c7/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2"}}, - {name = "pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/3b/b1/5e21d0b517434b7f33588ff76c177c5a167858cc38ef740608898cd329f2/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394"}}, - {name = "pyzmq-27.1.0-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/03/f2/44913a6ff6941905efc24a1acf3d3cb6146b636c546c7406c38c49c403d4/pyzmq-27.1.0-cp311-cp311-win32.whl",hashes = {sha256 = "6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f"}}, - {name = "pyzmq-27.1.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/23/6d/d8d92a0eb270a925c9b4dd039c0b4dc10abc2fcbc48331788824ef113935/pyzmq-27.1.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97"}}, - {name = "pyzmq-27.1.0-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ae/14/01afebc96c5abbbd713ecfc7469cfb1bc801c819a74ed5c9fad9a48801cb/pyzmq-27.1.0-cp311-cp311-win_arm64.whl",hashes = {sha256 = "eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07"}}, - {name = "pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/4c/c6/c4dcdecdbaa70969ee1fdced6d7b8f60cfabe64d25361f27ac4665a70620/pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066"}}, - {name = "pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl",url = "https://files.pythonhosted.org/packages/3e/79/f38c92eeaeb03a2ccc2ba9866f0439593bb08c5e3b714ac1d553e5c96e25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl",hashes = {sha256 = "ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604"}}, - {name = "pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c"}}, - {name = "pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",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",hashes = {sha256 = "f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271"}}, - {name = "pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/01/1b/5dbe84eefc86f48473947e2f41711aded97eecef1231f4558f1f02713c12/pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl",hashes = {sha256 = "c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "cffi; implementation_name == \"pypy\"", -] - -[[packages]] -name = "referencing" -version = "0.37.0" -requires-python = ">=3.10" -sdist = {name = "referencing-0.37.0.tar.gz", url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hashes = {sha256 = "44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}} -wheels = [ - {name = "referencing-0.37.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl",hashes = {sha256 = "381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "attrs>=22.2.0", - "rpds-py>=0.7.0", - "typing-extensions>=4.4.0; python_version < \"3.13\"", -] - -[[packages]] -name = "requests" -version = "2.33.1" -requires-python = ">=3.10" -sdist = {name = "requests-2.33.1.tar.gz", url = "https://files.pythonhosted.org/packages/5f/a4/98b9c7c6428a668bf7e42ebb7c79d576a1c3c1e3ae2d47e674b468388871/requests-2.33.1.tar.gz", hashes = {sha256 = "18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"}} -wheels = [ - {name = "requests-2.33.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl",hashes = {sha256 = "4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "certifi>=2023.5.7", - "charset-normalizer<4,>=2", - "idna<4,>=2.5", - "urllib3<3,>=1.26", -] - -[[packages]] -name = "roman-numerals" -version = "4.1.0" -requires-python = ">=3.10" -sdist = {name = "roman_numerals-4.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/ae/f9/41dc953bbeb056c17d5f7a519f50fdf010bd0553be2d630bc69d1e022703/roman_numerals-4.1.0.tar.gz", hashes = {sha256 = "1af8b147eb1405d5839e78aeb93131690495fe9da5c91856cb33ad55a7f1e5b2"}} -wheels = [ - {name = "roman_numerals-4.1.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/04/54/6f679c435d28e0a568d8e8a7c0a93a09010818634c3c3907fc98d8983770/roman_numerals-4.1.0-py3-none-any.whl",hashes = {sha256 = "647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "rpds-py" -version = "0.30.0" -requires-python = ">=3.10" -sdist = {name = "rpds_py-0.30.0.tar.gz", url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hashes = {sha256 = "dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}} -wheels = [ - {name = "rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl",hashes = {sha256 = "68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0"}}, - {name = "rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be"}}, - {name = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f"}}, - {name = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f"}}, - {name = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87"}}, - {name = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18"}}, - {name = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",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",hashes = {sha256 = "47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad"}}, - {name = "rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl",url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl",hashes = {sha256 = "b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07"}}, - {name = "rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f"}}, - {name = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65"}}, - {name = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl",hashes = {sha256 = "ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f"}}, - {name = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53"}}, - {name = "rpds_py-0.30.0-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl",hashes = {sha256 = "ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed"}}, - {name = "rpds_py-0.30.0-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl",hashes = {sha256 = "95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950"}}, - {name = "rpds_py-0.30.0-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl",hashes = {sha256 = "613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl",hashes = {sha256 = "7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",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",hashes = {sha256 = "626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl",url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl",hashes = {sha256 = "acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl",hashes = {sha256 = "3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl",hashes = {sha256 = "dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0"}}, - {name = "rpds_py-0.30.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3"}}, - {name = "rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl",hashes = {sha256 = "f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2"}}, - {name = "rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8"}}, - {name = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4"}}, - {name = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136"}}, - {name = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7"}}, - {name = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2"}}, - {name = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",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",hashes = {sha256 = "9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6"}}, - {name = "rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl",url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl",hashes = {sha256 = "9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e"}}, - {name = "rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d"}}, - {name = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7"}}, - {name = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31"}}, - {name = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95"}}, - {name = "rpds_py-0.30.0-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl",hashes = {sha256 = "b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d"}}, - {name = "rpds_py-0.30.0-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl",hashes = {sha256 = "806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15"}}, - {name = "rpds_py-0.30.0-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl",hashes = {sha256 = "d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl",hashes = {sha256 = "eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",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",hashes = {sha256 = "51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl",url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl",hashes = {sha256 = "eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl",hashes = {sha256 = "61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl",hashes = {sha256 = "3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6"}}, - {name = "rpds_py-0.30.0-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d"}}, - {name = "rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl",hashes = {sha256 = "a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad"}}, - {name = "rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05"}}, - {name = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28"}}, - {name = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd"}}, - {name = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f"}}, - {name = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1"}}, - {name = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",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",hashes = {sha256 = "47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23"}}, - {name = "rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl",url = "https://files.pythonhosted.org/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl",hashes = {sha256 = "2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6"}}, - {name = "rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51"}}, - {name = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5"}}, - {name = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e"}}, - {name = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394"}}, - {name = "rpds_py-0.30.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl",hashes = {sha256 = "1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf"}}, - {name = "rpds_py-0.30.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b"}}, - {name = "rpds_py-0.30.0-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl",hashes = {sha256 = "669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e"}}, - {name = "rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/4d/6e/f964e88b3d2abee2a82c1ac8366da848fce1c6d834dc2132c3fda3970290/rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl",hashes = {sha256 = "a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425"}}, - {name = "rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/94/ba/24e5ebb7c1c82e74c4e4f33b2112a5573ddc703915b13a073737b59b86e0/rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d"}}, - {name = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/84/86/04dbba1b087227747d64d80c3b74df946b986c57af0a9f0c98726d4d7a3b/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4"}}, - {name = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/42/bb/1463f0b1722b7f45431bdd468301991d1328b16cffe0b1c2918eba2c4eee/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f"}}, - {name = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/99/ee/2520700a5c1f2d76631f948b0736cdf9b0acb25abd0ca8e889b5c62ac2e3/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4"}}, - {name = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/e0/ad/bd0331f740f5705cc555a5e17fdf334671262160270962e69a2bdef3bf76/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97"}}, - {name = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",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",hashes = {sha256 = "33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89"}}, - {name = "rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl",url = "https://files.pythonhosted.org/packages/ab/2b/d88bb33294e3e0c76bc8f351a3721212713629ffca1700fa94979cb3eae8/rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl",hashes = {sha256 = "946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d"}}, - {name = "rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/50/32/c759a8d42bcb5289c1fac697cd92f6fe01a018dd937e62ae77e0e7f15702/rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038"}}, - {name = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/2b/81/e729761dbd55ddf5d84ec4ff1f47857f4374b0f19bdabfcf929164da3e24/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7"}}, - {name = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/14/f6/69066a924c3557c9c30baa6ec3a0aa07526305684c6f86c696b08860726c/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed"}}, - {name = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/5f/48/905896b1eb8a05630d20333d1d8ffd162394127b74ce0b0784ae04498d32/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85"}}, - {name = "rpds_py-0.30.0-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/22/16/cd3027c7e279d22e5eb431dd3c0fbc677bed58797fe7581e148f3f68818b/rpds_py-0.30.0-cp311-cp311-win32.whl",hashes = {sha256 = "55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c"}}, - {name = "rpds_py-0.30.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/fa/5b/e7b7aa136f28462b344e652ee010d4de26ee9fd16f1bfd5811f5153ccf89/rpds_py-0.30.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825"}}, - {name = "rpds_py-0.30.0-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/14/a6/364bba985e4c13658edb156640608f2c9e1d3ea3c81b27aa9d889fff0e31/rpds_py-0.30.0-cp311-cp311-win_arm64.whl",hashes = {sha256 = "47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/69/71/3f34339ee70521864411f8b6992e7ab13ac30d8e4e3309e07c7361767d91/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl",hashes = {sha256 = "c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/57/09/f183df9b8f2d66720d2ef71075c59f7e1b336bec7ee4c48f0a2b06857653/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/7a/68/5c2594e937253457342e078f0cc1ded3dd7b2ad59afdbf2d354869110a02/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/49/5c/31ef1afd70b4b4fbdb2800249f34c57c64beb687495b10aec0365f53dfc4/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/e3/63/0cfbea38d05756f3440ce6534d51a491d26176ac045e2707adc99bb6e60a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/42/e6/01e1f72a2456678b0f618fc9a1a13f882061690893c192fcad9f2926553a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",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",hashes = {sha256 = "58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl",url = "https://files.pythonhosted.org/packages/4a/b4/0a771378c5f16f8115f796d1f437950158679bcd2a7c68cf251cfb00ed5b/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl",hashes = {sha256 = "dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/36/d8/456dbba0af75049dc6f63ff295a2f92766b9d521fa00de67a2bd6427d57a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/13/64/b4d76f227d5c45a7e0b796c674fd81b0a6c4fbd48dc29271857d8219571c/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl",hashes = {sha256 = "dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/20/91/092bacadeda3edf92bf743cc96a7be133e13a39cdbfd7b5082e7ab638406/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl",hashes = {sha256 = "1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4"}}, - {name = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "scikit-learn" -version = "1.5.2" -requires-python = ">=3.9" -sdist = {name = "scikit_learn-1.5.2.tar.gz", url = "https://files.pythonhosted.org/packages/37/59/44985a2bdc95c74e34fef3d10cb5d93ce13b0e2a7baefffe1b53853b502d/scikit_learn-1.5.2.tar.gz", hashes = {sha256 = "b4237ed7b3fdd0a4882792e68ef2545d5baa50aca3bb45aa7df468138ad8f94d"}} -wheels = [ - {name = "scikit_learn-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/a4/50/8891028437858cc510e13578fe7046574a60c2aaaa92b02d64aac5b1b412/scikit_learn-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "e9a702e2de732bbb20d3bad29ebd77fc05a6b427dc49964300340e4c9328b3f5"}}, - {name = "scikit_learn-1.5.2-cp313-cp313-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d2/79/17feef8a1c14149436083bec0e61d7befb4812e272d5b20f9d79ea3e9ab1/scikit_learn-1.5.2-cp313-cp313-macosx_12_0_arm64.whl",hashes = {sha256 = "b0768ad641981f5d3a198430a1d31c3e044ed2e8a6f22166b4d546a5116d7908"}}, - {name = "scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/b1/c8/f08313f9e2e656bd0905930ae8bf99a573ea21c34666a813b749c338202f/scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "178ddd0a5cb0044464fc1bfc4cca5b1833bfc7bb022d70b05db8530da4bb3dd3"}}, - {name = "scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/a7/48/fbfb4dc72bed0fe31fe045fb30e924909ad03f717c36694351612973b1a9/scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "f7284ade780084d94505632241bf78c44ab3b6f1e8ccab3d2af58e0e950f9c12"}}, - {name = "scikit_learn-1.5.2-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a5/e7/0c869f9e60d225a77af90d2aefa7a4a4c0e745b149325d1450f0f0ce5399/scikit_learn-1.5.2-cp313-cp313-win_amd64.whl",hashes = {sha256 = "b7b0f9a0b1040830d38c39b91b3a44e1b643f4b36e36567b80b7c6bd2202a27f"}}, - {name = "scikit_learn-1.5.2-cp312-cp312-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/a4/db/b485c1ac54ff3bd9e7e6b39d3cc6609c4c76a65f52ab0a7b22b6c3ab0e9d/scikit_learn-1.5.2-cp312-cp312-macosx_10_9_x86_64.whl",hashes = {sha256 = "f932a02c3f4956dfb981391ab24bda1dbd90fe3d628e4b42caef3e041c67707a"}}, - {name = "scikit_learn-1.5.2-cp312-cp312-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/54/1a/7deb52fa23aebb855431ad659b3c6a2e1709ece582cb3a63d66905e735fe/scikit_learn-1.5.2-cp312-cp312-macosx_12_0_arm64.whl",hashes = {sha256 = "3b923d119d65b7bd555c73be5423bf06c0105678ce7e1f558cb4b40b0a5502b1"}}, - {name = "scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a1/32/4a7a205b14c11225609b75b28402c196e4396ac754dab6a81971b811781c/scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "f60021ec1574e56632be2a36b946f8143bf4e5e6af4a06d85281adc22938e0dd"}}, - {name = "scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/c6/29/044048c5e911373827c0e1d3051321b9183b2a4f8d4e2f11c08fcff83f13/scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "394397841449853c2290a32050382edaec3da89e35b3e03d6cc966aebc6a8ae6"}}, - {name = "scikit_learn-1.5.2-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/aa/ce/c0b912f2f31aeb1b756a6ba56bcd84dd1f8a148470526a48515a3f4d48cd/scikit_learn-1.5.2-cp312-cp312-win_amd64.whl",hashes = {sha256 = "57cc1786cfd6bd118220a92ede80270132aa353647684efa385a74244a41e3b1"}}, - {name = "scikit_learn-1.5.2-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/ff/91/609961972f694cb9520c4c3d201e377a26583e1eb83bc5a334c893729214/scikit_learn-1.5.2-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "03b6158efa3faaf1feea3faa884c840ebd61b6484167c711548fce208ea09445"}}, - {name = "scikit_learn-1.5.2-cp311-cp311-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/cd/7a/19fe32c810c5ceddafcfda16276d98df299c8649e24e84d4f00df4a91e01/scikit_learn-1.5.2-cp311-cp311-macosx_12_0_arm64.whl",hashes = {sha256 = "1ff45e26928d3b4eb767a8f14a9a6efbf1cbff7c05d1fb0f95f211a89fd4f5de"}}, - {name = "scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/4c/75/62e49f8a62bf3c60b0e64d0fce540578ee4f0e752765beb2e1dc7c6d6098/scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "f763897fe92d0e903aa4847b0aec0e68cadfff77e8a0687cabd946c89d17e675"}}, - {name = "scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/49/21/3723de321531c9745e40f1badafd821e029d346155b6c79704e0b7197552/scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "f8b0ccd4a902836493e026c03256e8b206656f91fbcc4fde28c57a5b752561f1"}}, - {name = "scikit_learn-1.5.2-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/17/1c/ccdd103cfcc9435a18819856fbbe0c20b8fa60bfc3343580de4be13f0668/scikit_learn-1.5.2-cp311-cp311-win_amd64.whl",hashes = {sha256 = "6c16d84a0d45e4894832b3c4d0bf73050939e21b99b01b6fd59cbb0cf39163b6"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "joblib>=1.2.0", - "numpy>=1.19.5", - "scipy>=1.6.0", - "threadpoolctl>=3.1.0", -] - -[[packages]] -name = "scipy" -version = "1.12.0" -requires-python = ">=3.9" -sdist = {name = "scipy-1.12.0.tar.gz", url = "https://files.pythonhosted.org/packages/30/85/cdbf2c3c460fe5aae812917866392068a88d02f07de0fe31ce738734c477/scipy-1.12.0.tar.gz", hashes = {sha256 = "4bf5abab8a36d20193c698b0f1fc282c1d083c94723902c447e5d2f1780936a3"}} -wheels = [ - {name = "scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/0d/4a/b2b2cae0c5dfd46361245a67102886ed7188805bdf7044e36fe838bbcf26/scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl",hashes = {sha256 = "e7e76cc48638228212c747ada851ef355c2bb5e7f939e10952bc504c11f4e372"}}, - {name = "scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/71/ba/744bbdd65eb3fce1412dd4633fc425ad39e6b4068b5b158aee1cd3afeb54/scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl",hashes = {sha256 = "f7ce148dffcd64ade37b2df9315541f9adad6efcaa86866ee7dd5db0c8f041c3"}}, - {name = "scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/db/fd/81feac476e1ae495b51b8c3636aee1f50a1c5ca2a3557f5b0043d4e2fb02/scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "9c39f92041f490422924dfdb782527a4abddf4707616e07b021de33467f917bc"}}, - {name = "scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/11/7d/850bfe9462fff393130519eb54f97d43ad9c280ec4297b4cb98b7c2e96cd/scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "a7ebda398f86e56178c2fa94cad15bf457a218a54a35c2a7b4490b9f9cb2676c"}}, - {name = "scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/7e/7f/504b7b3834d8c9229831c6c58a44943e29a34004eeb34c7ff150add4e001/scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl",hashes = {sha256 = "95e5c750d55cf518c398a8240571b0e0782c2d5a703250872f36eaf737751338"}}, - {name = "scipy-1.12.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f3/31/91a2a3c5eb85d2bfa86d7c98f2df5d77dcdefb3d80ca9f9037ad04393acf/scipy-1.12.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "e646d8571804a304e1da01040d21577685ce8e2db08ac58e543eaca063453e1c"}}, - {name = "scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/c3/32/7915195ca4643508fe9730691eaed57b879646279572b10b02bdadf165c5/scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "408c68423f9de16cb9e602528be4ce0d6312b05001f3de61fe9ec8b1263cad08"}}, - {name = "scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/21/d4/e6c57acc61e59cd46acca27af1f400094d5dee218e372cc604b8162b97cb/scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl",hashes = {sha256 = "5adfad5dbf0163397beb4aca679187d24aec085343755fcdbdeb32b3679f254c"}}, - {name = "scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/e3/c5/d40abc1a857c1c6519e1a4e096d6aee86861eddac019fb736b6af8a58d25/scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "c3003652496f6e7c387b1cf63f4bb720951cfa18907e998ea551e6de51a04467"}}, - {name = "scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d4/b8/7169935f9a2ea9e274ad8c21d6133d492079e6ebc3fc69a915c2375616b0/scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "8b8066bce124ee5531d12a74b617d9ac0ea59245246410e19bca549656d9a40a"}}, - {name = "scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/64/e7/4dbb779d09d1cb757ddbe42cae7c4fe8270497566bb902138d637b04d88c/scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "8bee4993817e204d761dba10dbab0774ba5a8612e57e81319ea04d84945375ba"}}, - {name = "scipy-1.12.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/9a/25/5b30cb3efc9566f0ebeaeca1976150316353c17031ad7868ef46de5ab8dc/scipy-1.12.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "a24024d45ce9a675c1fb8494e8e5244efea1c7a09c60beb1eeb80373d0fecc70"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "numpy<1.29.0,>=1.22.4", -] - -[[packages]] -name = "six" -version = "1.17.0" -requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -sdist = {name = "six-1.17.0.tar.gz", url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hashes = {sha256 = "ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}} -wheels = [ - {name = "six-1.17.0-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl",hashes = {sha256 = "4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "snowballstemmer" -version = "3.0.1" -requires-python = "!=3.0.*,!=3.1.*,!=3.2.*" -sdist = {name = "snowballstemmer-3.0.1.tar.gz", url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hashes = {sha256 = "6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}} -wheels = [ - {name = "snowballstemmer-3.0.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl",hashes = {sha256 = "6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "soupsieve" -version = "2.8.3" -requires-python = ">=3.9" -sdist = {name = "soupsieve-2.8.3.tar.gz", url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hashes = {sha256 = "3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349"}} -wheels = [ - {name = "soupsieve-2.8.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl",hashes = {sha256 = "ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "sphinx" -version = "9.0.4" -requires-python = ">=3.11" -sdist = {name = "sphinx-9.0.4.tar.gz", url = "https://files.pythonhosted.org/packages/42/50/a8c6ccc36d5eacdfd7913ddccd15a9cee03ecafc5ee2bc40e1f168d85022/sphinx-9.0.4.tar.gz", hashes = {sha256 = "594ef59d042972abbc581d8baa577404abe4e6c3b04ef61bd7fc2acbd51f3fa3"}} -wheels = [ - {name = "sphinx-9.0.4-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/c6/3f/4bbd76424c393caead2e1eb89777f575dee5c8653e2d4b6afd7a564f5974/sphinx-9.0.4-py3-none-any.whl",hashes = {sha256 = "5bebc595a5e943ea248b99c13814c1c5e10b3ece718976824ffa7959ff95fffb"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "Jinja2>=3.1", - "Pygments>=2.17", - "alabaster>=0.7.14", - "babel>=2.13", - "colorama>=0.4.6; sys_platform == \"win32\"", - "docutils<0.23,>=0.20", - "imagesize>=1.3", - "packaging>=23.0", - "requests>=2.30.0", - "roman-numerals>=1.0.0", - "snowballstemmer>=2.2", - "sphinxcontrib-applehelp>=1.0.7", - "sphinxcontrib-devhelp>=1.0.6", - "sphinxcontrib-htmlhelp>=2.0.6", - "sphinxcontrib-jsmath>=1.0.1", - "sphinxcontrib-qthelp>=1.0.6", - "sphinxcontrib-serializinghtml>=1.1.9", -] - -[[packages]] -name = "sphinx-autobuild" -version = "2025.8.25" -requires-python = ">=3.11" -sdist = {name = "sphinx_autobuild-2025.8.25.tar.gz", url = "https://files.pythonhosted.org/packages/e0/3c/a59a3a453d4133777f7ed2e83c80b7dc817d43c74b74298ca0af869662ad/sphinx_autobuild-2025.8.25.tar.gz", hashes = {sha256 = "9cf5aab32853c8c31af572e4fecdc09c997e2b8be5a07daf2a389e270e85b213"}} -wheels = [ - {name = "sphinx_autobuild-2025.8.25-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d7/20/56411b52f917696995f5ad27d2ea7e9492c84a043c5b49a3a3173573cd93/sphinx_autobuild-2025.8.25-py3-none-any.whl",hashes = {sha256 = "b750ac7d5a18603e4665294323fd20f6dcc0a984117026d1986704fa68f0379a"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "Sphinx", - "colorama>=0.4.6", - "starlette>=0.35", - "uvicorn>=0.25", - "watchfiles>=0.20", - "websockets>=11", -] - -[[packages]] -name = "sphinx-basic-ng" -version = "1.0.0b2" -requires-python = ">=3.7" -sdist = {name = "sphinx_basic_ng-1.0.0b2.tar.gz", url = "https://files.pythonhosted.org/packages/98/0b/a866924ded68efec7a1759587a4e478aec7559d8165fac8b2ad1c0e774d6/sphinx_basic_ng-1.0.0b2.tar.gz", hashes = {sha256 = "9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9"}} -wheels = [ - {name = "sphinx_basic_ng-1.0.0b2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/3c/dd/018ce05c532a22007ac58d4f45232514cd9d6dd0ee1dc374e309db830983/sphinx_basic_ng-1.0.0b2-py3-none-any.whl",hashes = {sha256 = "eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "sphinx>=4.0", -] - -[[packages]] -name = "sphinx-copybutton" -version = "0.5.2" -requires-python = ">=3.7" -sdist = {name = "sphinx-copybutton-0.5.2.tar.gz", url = "https://files.pythonhosted.org/packages/fc/2b/a964715e7f5295f77509e59309959f4125122d648f86b4fe7d70ca1d882c/sphinx-copybutton-0.5.2.tar.gz", hashes = {sha256 = "4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}} -wheels = [ - {name = "sphinx_copybutton-0.5.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/9e/48/1ea60e74949eecb12cdd6ac43987f9fd331156388dcc2319b45e2ebb81bf/sphinx_copybutton-0.5.2-py3-none-any.whl",hashes = {sha256 = "fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "sphinx>=1.8", -] - -[[packages]] -name = "sphinx-design" -version = "0.7.0" -requires-python = ">=3.11" -sdist = {name = "sphinx_design-0.7.0.tar.gz", url = "https://files.pythonhosted.org/packages/13/7b/804f311da4663a4aecc6cf7abd83443f3d4ded970826d0c958edc77d4527/sphinx_design-0.7.0.tar.gz", hashes = {sha256 = "d2a3f5b19c24b916adb52f97c5f00efab4009ca337812001109084a740ec9b7a"}} -wheels = [ - {name = "sphinx_design-0.7.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/30/cf/45dd359f6ca0c3762ce0490f681da242f0530c49c81050c035c016bfdd3a/sphinx_design-0.7.0-py3-none-any.whl",hashes = {sha256 = "f82bf179951d58f55dca78ab3706aeafa496b741a91b1911d371441127d64282"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "sphinx<10,>=7", -] - -[[packages]] -name = "sphinx-gallery" -version = "0.20.0" -requires-python = ">=3.10" -sdist = {name = "sphinx_gallery-0.20.0.tar.gz", url = "https://files.pythonhosted.org/packages/5f/14/9238ac61932299b38c20c7c37dbfe60348c0348ea4d400f9ef25875b3bf7/sphinx_gallery-0.20.0.tar.gz", hashes = {sha256 = "70281510c6183d812d3595957005ccf555c5a793f207410f6cd16a25bf08d735"}} -wheels = [ - {name = "sphinx_gallery-0.20.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/27/fd/818a53d4da56ef2da7b08f77bb3a825635941d1fcc6b6a490995dec1a81c/sphinx_gallery-0.20.0-py3-none-any.whl",hashes = {sha256 = "188b7456e269649945825661b76cdbfbf0b70c2cfd5b75c9a11fe52519879e4d"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "pillow", - "sphinx>=5", -] - -[[packages]] -name = "sphinxcontrib-applehelp" -version = "2.0.0" -requires-python = ">=3.9" -sdist = {name = "sphinxcontrib_applehelp-2.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hashes = {sha256 = "2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}} -wheels = [ - {name = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl",hashes = {sha256 = "4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "sphinxcontrib-devhelp" -version = "2.0.0" -requires-python = ">=3.9" -sdist = {name = "sphinxcontrib_devhelp-2.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hashes = {sha256 = "411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}} -wheels = [ - {name = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl",hashes = {sha256 = "aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "sphinxcontrib-htmlhelp" -version = "2.1.0" -requires-python = ">=3.9" -sdist = {name = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hashes = {sha256 = "c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}} -wheels = [ - {name = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl",hashes = {sha256 = "166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -requires-python = ">=3.5" -sdist = {name = "sphinxcontrib-jsmath-1.0.1.tar.gz", url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hashes = {sha256 = "a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}} -wheels = [ - {name = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl",hashes = {sha256 = "2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "sphinxcontrib-qthelp" -version = "2.0.0" -requires-python = ">=3.9" -sdist = {name = "sphinxcontrib_qthelp-2.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hashes = {sha256 = "4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}} -wheels = [ - {name = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl",hashes = {sha256 = "b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "sphinxcontrib-serializinghtml" -version = "2.0.0" -requires-python = ">=3.9" -sdist = {name = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hashes = {sha256 = "e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}} -wheels = [ - {name = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl",hashes = {sha256 = "6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "sphinxtesters" -version = "0.2.4" -requires-python = ">=3.8" -sdist = {name = "sphinxtesters-0.2.4.tar.gz", url = "https://files.pythonhosted.org/packages/aa/08/93af63fc5c6fd4c66b84a92c0048c5d2134fd168c6d763b01a476a3496f1/sphinxtesters-0.2.4.tar.gz", hashes = {sha256 = "09c456e1cd61ec99b64851e2990d2152fdf05bb53d87f3b294f22d73f939d6ca"}} -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "sphinx>=1.4", -] - -[[packages]] -name = "stack-data" -version = "0.6.3" -sdist = {name = "stack_data-0.6.3.tar.gz", url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hashes = {sha256 = "836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}} -wheels = [ - {name = "stack_data-0.6.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl",hashes = {sha256 = "d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "asttokens>=2.1.0", - "executing>=1.2.0", - "pure-eval", -] - -[[packages]] -name = "starlette" -version = "1.0.0" -requires-python = ">=3.10" -sdist = {name = "starlette-1.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/81/69/17425771797c36cded50b7fe44e850315d039f28b15901ab44839e70b593/starlette-1.0.0.tar.gz", hashes = {sha256 = "6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149"}} -wheels = [ - {name = "starlette-1.0.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl",hashes = {sha256 = "d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "anyio<5,>=3.6.2", - "typing-extensions>=4.10.0; python_version < \"3.13\"", -] - -[[packages]] -name = "statsmodels" -version = "0.14.1" -requires-python = ">=3.8" -sdist = {name = "statsmodels-0.14.1.tar.gz", url = "https://files.pythonhosted.org/packages/4b/80/c4e279a6a13468ae2f1f01af2a07ddb44f397ac4d7636af13c5b3b83dde1/statsmodels-0.14.1.tar.gz", hashes = {sha256 = "2260efdc1ef89f39c670a0bd8151b1d0843567781bcafec6cda0534eb47a94f6"}} -wheels = [ - {name = "statsmodels-0.14.1-cp312-cp312-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/2e/e7/636f44ea2e42327feaf7e82d9943a17010b6bd1d2aee1691a82f6f8df26d/statsmodels-0.14.1-cp312-cp312-macosx_10_9_x86_64.whl",hashes = {sha256 = "f32a7cd424cf33304a54daee39d32cccf1d0265e652c920adeaeedff6d576457"}}, - {name = "statsmodels-0.14.1-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/dc/5e/ab969ede80024d1d988ffd4f60c2026ae16b647c41f867fabaa4d4e77cb8/statsmodels-0.14.1-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "f8c30181c084173d662aaf0531867667be2ff1bee103b84feb64f149f792dbd2"}}, - {name = "statsmodels-0.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/35/41/1000c2eb2ad62530a2c2a59a6de987bc8acb3362eb4c93a476e4a541d11c/statsmodels-0.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "2de2b97413913d52ad6342dece2d653e77f78620013b7705fad291d4e4266ccb"}}, - {name = "statsmodels-0.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d2/21/929083f9f4fa876ae3cf0d37483b52acc71c050afd4e802cbe5d7ed2f1fa/statsmodels-0.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "c3420f88289c593ba2bca33619023059c476674c160733bd7d858564787c83d3"}}, - {name = "statsmodels-0.14.1-cp312-cp312-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/05/00/82b2f1a53b94b4c6f540efd9f1d8ff583d4e616908e5faf61b497b9e4814/statsmodels-0.14.1-cp312-cp312-musllinux_1_1_x86_64.whl",hashes = {sha256 = "c008e16096f24f0514e53907890ccac6589a16ad6c81c218f2ee6752fdada555"}}, - {name = "statsmodels-0.14.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/52/fc/4c0e654ab177558a657eaba369e5a25fbf700f95f1d122f6c083525d58c4/statsmodels-0.14.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "bc0351d279c4e080f0ce638a3d886d312aa29eade96042e3ba0a73771b1abdfb"}}, - {name = "statsmodels-0.14.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/59/21/67f47ce99670a0f14f45419d37544fb5b2431c2f12ba34680f5729464cbe/statsmodels-0.14.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "b69a63ad6c979a6e4cde11870ffa727c76a318c225a7e509f031fbbdfb4e416a"}}, - {name = "statsmodels-0.14.1-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a1/ab/a43022ffd46fe5083773f36285a334713023ae86bab828708d17993fbb7b/statsmodels-0.14.1-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "7562cb18a90a114f39fab6f1c25b9c7b39d9cd5f433d0044b430ca9d44a8b52c"}}, - {name = "statsmodels-0.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/9a/f4/f9b83f8ffe00bc8d22ac6916ced94b1f622909c2f168bdd38d1afb7046e7/statsmodels-0.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "b3abaca4b963259a2bf349c7609cfbb0ce64ad5fb3d92d6f08e21453e4890248"}}, - {name = "statsmodels-0.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d7/e4/5c13fa7ac57bbee2bd0061efff851891a5d166587958d3aa5b6328f23f00/statsmodels-0.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "b0f727fe697f6406d5f677b67211abe5a55101896abdfacdb3f38410405f6ad8"}}, - {name = "statsmodels-0.14.1-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/6a/e7/4a962975321d69c403089c175bb6735b517a31e31f5cdab8e37eedfdcea0/statsmodels-0.14.1-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "b6838ac6bdb286daabb5e91af90fd4258f09d0cec9aace78cc441cb2b17df428"}}, - {name = "statsmodels-0.14.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/9a/b2/13833f94076dcc2709137fee92157ef5a0099a11ddff4f4b7cb301b35357/statsmodels-0.14.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "709bfcef2dbe66f705b17e56d1021abad02243ee1a5d1efdb90f9bad8b06a329"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [ - "numpy<2,>=1.18", - "numpy<2,>=1.22.3; python_version == \"3.10\" and platform_system == \"Windows\" and platform_python_implementation != \"PyPy\"", - "packaging>=21.3", - "pandas!=2.1.0,>=1.0", - "patsy>=0.5.4", - "scipy!=1.9.2,>=1.4", - "scipy!=1.9.2,>=1.4; sys_platform == \"win32\"", -] - -[[packages]] -name = "texext" -version = "0.6.8" -sdist = {name = "texext-0.6.8.tar.gz", url = "https://files.pythonhosted.org/packages/a6/73/5dc7e7955e4c5a45de3ef1467cfe498233cc3aba2a3c50ff41a55d667c42/texext-0.6.8.tar.gz", hashes = {sha256 = "6c3ccc5578f93a1bd0051fcba25e92d259620d3d9c9031738570e7d78603e7a3"}} -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "docutils>=0.19", - "sphinx>=7", -] - -[[packages]] -name = "threadpoolctl" -version = "3.6.0" -requires-python = ">=3.9" -sdist = {name = "threadpoolctl-3.6.0.tar.gz", url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hashes = {sha256 = "8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e"}} -wheels = [ - {name = "threadpoolctl-3.6.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl",hashes = {sha256 = "43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "tinycss2" -version = "1.4.0" -requires-python = ">=3.8" -sdist = {name = "tinycss2-1.4.0.tar.gz", url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hashes = {sha256 = "10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7"}} -wheels = [ - {name = "tinycss2-1.4.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl",hashes = {sha256 = "3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "webencodings>=0.4", -] - -[[packages]] -name = "tomlkit" -version = "0.14.0" -requires-python = ">=3.9" -sdist = {name = "tomlkit-0.14.0.tar.gz", url = "https://files.pythonhosted.org/packages/c3/af/14b24e41977adb296d6bd1fb59402cf7d60ce364f90c890bd2ec65c43b5a/tomlkit-0.14.0.tar.gz", hashes = {sha256 = "cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064"}} -wheels = [ - {name = "tomlkit-0.14.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl",hashes = {sha256 = "592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "tornado" -version = "6.5.5" -requires-python = ">=3.9" -sdist = {name = "tornado-6.5.5.tar.gz", url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hashes = {sha256 = "192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9"}} -wheels = [ - {name = "tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl",hashes = {sha256 = "487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa"}}, - {name = "tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl",hashes = {sha256 = "65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521"}}, - {name = "tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",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",hashes = {sha256 = "e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5"}}, - {name = "tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",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",hashes = {sha256 = "435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07"}}, - {name = "tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl",hashes = {sha256 = "3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e"}}, - {name = "tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl",hashes = {sha256 = "36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca"}}, - {name = "tornado-6.5.5-cp39-abi3-win32.whl",url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl",hashes = {sha256 = "dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7"}}, - {name = "tornado-6.5.5-cp39-abi3-win_amd64.whl",url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl",hashes = {sha256 = "6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b"}}, - {name = "tornado-6.5.5-cp39-abi3-win_arm64.whl",url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl",hashes = {sha256 = "2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "traitlets" -version = "5.14.3" -requires-python = ">=3.8" -sdist = {name = "traitlets-5.14.3.tar.gz", url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hashes = {sha256 = "9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}} -wheels = [ - {name = "traitlets-5.14.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl",hashes = {sha256 = "b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "typing-extensions" -version = "4.15.0" -requires-python = ">=3.9" -sdist = {name = "typing_extensions-4.15.0.tar.gz", url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hashes = {sha256 = "0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}} -wheels = [ - {name = "typing_extensions-4.15.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl",hashes = {sha256 = "f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "tzdata" -version = "2026.1" -requires-python = ">=2" -sdist = {name = "tzdata-2026.1.tar.gz", url = "https://files.pythonhosted.org/packages/19/f5/cd531b2d15a671a40c0f66cf06bc3570a12cd56eef98960068ebbad1bf5a/tzdata-2026.1.tar.gz", hashes = {sha256 = "67658a1903c75917309e753fdc349ac0efd8c27db7a0cb406a25be4840f87f98"}} -wheels = [ - {name = "tzdata-2026.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b0/70/d460bd685a170790ec89317e9bd33047988e4bce507b831f5db771e142de/tzdata-2026.1-py2.py3-none-any.whl",hashes = {sha256 = "4b1d2be7ac37ceafd7327b961aa3a54e467efbdb563a23655fbfe0d39cfc42a9"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "urllib3" -version = "2.6.3" -requires-python = ">=3.9" -sdist = {name = "urllib3-2.6.3.tar.gz", url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hashes = {sha256 = "1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}} -wheels = [ - {name = "urllib3-2.6.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl",hashes = {sha256 = "bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}}, -] -marker = "\"default\" in dependency_groups or \"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "uvicorn" -version = "0.44.0" -requires-python = ">=3.10" -sdist = {name = "uvicorn-0.44.0.tar.gz", url = "https://files.pythonhosted.org/packages/5e/da/6eee1ff8b6cbeed47eeb5229749168e81eb4b7b999a1a15a7176e51410c9/uvicorn-0.44.0.tar.gz", hashes = {sha256 = "6c942071b68f07e178264b9152f1f16dfac5da85880c4ce06366a96d70d4f31e"}} -wheels = [ - {name = "uvicorn-0.44.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b7/23/a5bbd9600dd607411fa644c06ff4951bec3a4d82c4b852374024359c19c0/uvicorn-0.44.0-py3-none-any.whl",hashes = {sha256 = "ce937c99a2cc70279556967274414c087888e8cec9f9c94644dfca11bd3ced89"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "click>=7.0", - "h11>=0.8", - "typing-extensions>=4.0; python_version < \"3.11\"", -] - -[[packages]] -name = "virtualenv" -version = "21.2.4" -requires-python = ">=3.8" -sdist = {name = "virtualenv-21.2.4.tar.gz", url = "https://files.pythonhosted.org/packages/0c/98/3a7e644e19cb26133488caff231be390579860bbbb3da35913c49a1d0a46/virtualenv-21.2.4.tar.gz", hashes = {sha256 = "b294ef68192638004d72524ce7ef303e9d0cf5a44c95ce2e54a7500a6381cada"}} -wheels = [ - {name = "virtualenv-21.2.4-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/27/8d/edd0bd910ff803c308ee9a6b7778621af0d10252219ad9f19ef4d4982a61/virtualenv-21.2.4-py3-none-any.whl",hashes = {sha256 = "29d21e941795206138d0f22f4e45ff7050e5da6c6472299fb7103318763861ac"}}, -] -marker = "\"pre-commit\" in extras" - -[packages.tool.pdm] -dependencies = [ - "distlib<1,>=0.3.7", - "filelock<4,>=3.24.2; python_version >= \"3.10\"", - "filelock<=3.19.1,>=3.16.1; python_version < \"3.10\"", - "importlib-metadata>=6.6; python_version < \"3.8\"", - "platformdirs<5,>=3.9.1", - "python-discovery>=1.2.2", - "typing-extensions>=4.13.2; python_version < \"3.11\"", -] - -[[packages]] -name = "watchfiles" -version = "1.1.1" -requires-python = ">=3.9" -sdist = {name = "watchfiles-1.1.1.tar.gz", url = "https://files.pythonhosted.org/packages/c2/c9/8869df9b2a2d6c59d79220a4db37679e74f807c559ffe5265e08b227a210/watchfiles-1.1.1.tar.gz", hashes = {sha256 = "a173cb5c16c4f40ab19cecf48a534c409f7ea983ab8fed0741304a1c0a31b3f2"}} -wheels = [ - {name = "watchfiles-1.1.1-cp314-cp314-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/c3/f4/0872229324ef69b2c3edec35e84bd57a1289e7d3fe74588048ed8947a323/watchfiles-1.1.1-cp314-cp314-macosx_10_12_x86_64.whl",hashes = {sha256 = "d1715143123baeeaeadec0528bb7441103979a1d5f6fd0e1f915383fea7ea6d5"}}, - {name = "watchfiles-1.1.1-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7b/22/16d5331eaed1cb107b873f6ae1b69e9ced582fcf0c59a50cd84f403b1c32/watchfiles-1.1.1-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "39574d6370c4579d7f5d0ad940ce5b20db0e4117444e39b6d8f99db5676c52fd"}}, - {name = "watchfiles-1.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/b2/7e/5643bfff5acb6539b18483128fdc0ef2cccc94a5b8fbda130c823e8ed636/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "7365b92c2e69ee952902e8f70f3ba6360d0d596d9299d55d7d386df84b6941fb"}}, - {name = "watchfiles-1.1.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/51/2e/c410993ba5025a9f9357c376f48976ef0e1b1aefb73b97a5ae01a5972755/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "bfff9740c69c0e4ed32416f013f3c45e2ae42ccedd1167ef2d805c000b6c71a5"}}, - {name = "watchfiles-1.1.1-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/8e/a4/2df3b404469122e8680f0fcd06079317e48db58a2da2950fb45020947734/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "b27cf2eb1dda37b2089e3907d8ea92922b673c0c427886d4edc6b94d8dfe5db3"}}, - {name = "watchfiles-1.1.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/ea/84/4587ba5b1f267167ee715b7f66e6382cca6938e0a4b870adad93e44747e6/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "526e86aced14a65a5b0ec50827c745597c782ff46b571dbfe46192ab9e0b3c33"}}, - {name = "watchfiles-1.1.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/6a/0f/c6988c91d06e93cd0bb3d4a808bcf32375ca1904609835c3031799e3ecae/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "04e78dd0b6352db95507fd8cb46f39d185cf8c74e4cf1e4fbad1d3df96faf510"}}, - {name = "watchfiles-1.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/b4/36/ded8aebea91919485b7bbabbd14f5f359326cb5ec218cd67074d1e426d74/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "5c85794a4cfa094714fb9c08d4a218375b2b95b8ed1666e8677c349906246c05"}}, - {name = "watchfiles-1.1.1-cp314-cp314-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/98/e0/8c9bdba88af756a2fce230dd365fab2baf927ba42cd47521ee7498fd5211/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_aarch64.whl",hashes = {sha256 = "74d5012b7630714b66be7b7b7a78855ef7ad58e8650c73afc4c076a1f480a8d6"}}, - {name = "watchfiles-1.1.1-cp314-cp314-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/2a/84/a95db05354bf2d19e438520d92a8ca475e578c647f78f53197f5a2f17aaf/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_x86_64.whl",hashes = {sha256 = "8fbe85cb3201c7d380d3d0b90e63d520f15d6afe217165d7f98c9c649654db81"}}, - {name = "watchfiles-1.1.1-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/1d/ce/d8acdc8de545de995c339be67711e474c77d643555a9bb74a9334252bd55/watchfiles-1.1.1-cp314-cp314-win32.whl",hashes = {sha256 = "3fa0b59c92278b5a7800d3ee7733da9d096d4aabcfabb9a928918bd276ef9b9b"}}, - {name = "watchfiles-1.1.1-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/c4/c9/a74487f72d0451524be827e8edec251da0cc1fcf111646a511ae752e1a3d/watchfiles-1.1.1-cp314-cp314-win_amd64.whl",hashes = {sha256 = "c2047d0b6cea13b3316bdbafbfa0c4228ae593d995030fda39089d36e64fc03a"}}, - {name = "watchfiles-1.1.1-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/df/b8/8ac000702cdd496cdce998c6f4ee0ca1f15977bba51bdf07d872ebdfc34c/watchfiles-1.1.1-cp314-cp314-win_arm64.whl",hashes = {sha256 = "842178b126593addc05acf6fce960d28bc5fae7afbaa2c6c1b3a7b9460e5be02"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/47/a8/e3af2184707c29f0f14b1963c0aace6529f9d1b8582d5b99f31bbf42f59e/watchfiles-1.1.1-cp314-cp314t-macosx_10_12_x86_64.whl",hashes = {sha256 = "88863fbbc1a7312972f1c511f202eb30866370ebb8493aef2812b9ff28156a21"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c0/ec/e47e307c2f4bd75f9f9e8afbe3876679b18e1bcec449beca132a1c5ffb2d/watchfiles-1.1.1-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "55c7475190662e202c08c6c0f4d9e345a29367438cf8e8037f3155e10a88d5a5"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/d5/a0/ad235642118090f66e7b2f18fd5c42082418404a79205cdfca50b6309c13/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "3f53fa183d53a1d7a8852277c92b967ae99c2d4dcee2bfacff8868e6e30b15f7"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/df/85/97fa10fd5ff3332ae17e7e40e20784e419e28521549780869f1413742e9d/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "6aae418a8b323732fa89721d86f39ec8f092fc2af67f4217a2b07fd3e93c6101"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/47/c2/9059c2e8966ea5ce678166617a7f75ecba6164375f3b288e50a40dc6d489/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "f096076119da54a6080e8920cbdaac3dbee667eb91dcc5e5b78840b87415bd44"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/94/44/d90a9ec8ac309bc26db808a13e7bfc0e4e78b6fc051078a554e132e80160/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "00485f441d183717038ed2e887a7c868154f216877653121068107b227a2f64c"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/95/68/4e3479b20ca305cfc561db3ed207a8a1c745ee32bf24f2026a129d0ddb6e/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "a55f3e9e493158d7bfdb60a1165035f1cf7d320914e7b7ea83fe22c6023b58fc"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/4f/55/2af26693fd15165c4ff7857e38330e1b61ab8c37d15dc79118cdba115b7a/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "8c91ed27800188c2ae96d16e3149f199d62f86c7af5f5f4d2c61a3ed8cd3666c"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/66/1d/d0d200b10c9311ec25d2273f8aad8c3ef7cc7ea11808022501811208a750/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_aarch64.whl",hashes = {sha256 = "311ff15a0bae3714ffb603e6ba6dbfba4065ab60865d15a6ec544133bdb21099"}}, - {name = "watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/e3/bd/fa9bb053192491b3867ba07d2343d9f2252e00811567d30ae8d0f78136fe/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl",hashes = {sha256 = "a916a2932da8f8ab582f242c065f5c81bed3462849ca79ee357dd9551b0e9b01"}}, - {name = "watchfiles-1.1.1-cp313-cp313-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/bb/f4/f750b29225fe77139f7ae5de89d4949f5a99f934c65a1f1c0b248f26f747/watchfiles-1.1.1-cp313-cp313-macosx_10_12_x86_64.whl",hashes = {sha256 = "130e4876309e8686a5e37dba7d5e9bc77e6ed908266996ca26572437a5271e18"}}, - {name = "watchfiles-1.1.1-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/2b/f9/f07a295cde762644aa4c4bb0f88921d2d141af45e735b965fb2e87858328/watchfiles-1.1.1-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "5f3bde70f157f84ece3765b42b4a52c6ac1a50334903c6eaf765362f6ccca88a"}}, - {name = "watchfiles-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/bc/11/fc2502457e0bea39a5c958d86d2cb69e407a4d00b85735ca724bfa6e0d1a/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "14e0b1fe858430fc0251737ef3824c54027bedb8c37c38114488b8e131cf8219"}}, - {name = "watchfiles-1.1.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/e3/1f/d66bc15ea0b728df3ed96a539c777acfcad0eb78555ad9efcaa1274688f0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "f27db948078f3823a6bb3b465180db8ebecf26dd5dae6f6180bd87383b6b4428"}}, - {name = "watchfiles-1.1.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/be/90/9f4a65c0aec3ccf032703e6db02d89a157462fbb2cf20dd415128251cac0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "059098c3a429f62fc98e8ec62b982230ef2c8df68c79e826e37b895bc359a9c0"}}, - {name = "watchfiles-1.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/37/57/ee347af605d867f712be7029bb94c8c071732a4b44792e3176fa3c612d39/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "bfb5862016acc9b869bb57284e6cb35fdf8e22fe59f7548858e2f971d045f150"}}, - {name = "watchfiles-1.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/a8/78/cc5ab0b86c122047f75e8fc471c67a04dee395daf847d3e59381996c8707/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "319b27255aacd9923b8a276bb14d21a5f7ff82564c744235fc5eae58d95422ae"}}, - {name = "watchfiles-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/62/da/def65b170a3815af7bd40a3e7010bf6ab53089ef1b75d05dd5385b87cf08/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "c755367e51db90e75b19454b680903631d41f9e3607fbd941d296a020c2d752d"}}, - {name = "watchfiles-1.1.1-cp313-cp313-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/57/99/da6573ba71166e82d288d4df0839128004c67d2778d3b566c138695f5c0b/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_aarch64.whl",hashes = {sha256 = "c22c776292a23bfc7237a98f791b9ad3144b02116ff10d820829ce62dff46d0b"}}, - {name = "watchfiles-1.1.1-cp313-cp313-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/a8/51/7439c4dd39511368849eb1e53279cd3454b4a4dbace80bab88feeb83c6b5/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_x86_64.whl",hashes = {sha256 = "3a476189be23c3686bc2f4321dd501cb329c0a0469e77b7b534ee10129ae6374"}}, - {name = "watchfiles-1.1.1-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/95/9c/8ed97d4bba5db6fdcdb2b298d3898f2dd5c20f6b73aee04eabe56c59677e/watchfiles-1.1.1-cp313-cp313-win32.whl",hashes = {sha256 = "bf0a91bfb5574a2f7fc223cf95eeea79abfefa404bf1ea5e339c0c1560ae99a0"}}, - {name = "watchfiles-1.1.1-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/1f/f3/c14e28429f744a260d8ceae18bf58c1d5fa56b50d006a7a9f80e1882cb0d/watchfiles-1.1.1-cp313-cp313-win_amd64.whl",hashes = {sha256 = "52e06553899e11e8074503c8e716d574adeeb7e68913115c4b3653c53f9bae42"}}, - {name = "watchfiles-1.1.1-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/dc/61/fe0e56c40d5cd29523e398d31153218718c5786b5e636d9ae8ae79453d27/watchfiles-1.1.1-cp313-cp313-win_arm64.whl",hashes = {sha256 = "ac3cc5759570cd02662b15fbcd9d917f7ecd47efe0d6b40474eafd246f91ea18"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/79/42/e0a7d749626f1e28c7108a99fb9bf524b501bbbeb9b261ceecde644d5a07/watchfiles-1.1.1-cp313-cp313t-macosx_10_12_x86_64.whl",hashes = {sha256 = "563b116874a9a7ce6f96f87cd0b94f7faf92d08d0021e837796f0a14318ef8da"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/15/49/08732f90ce0fbbc13913f9f215c689cfc9ced345fb1bcd8829a50007cc8d/watchfiles-1.1.1-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "3ad9fe1dae4ab4212d8c91e80b832425e24f421703b5a42ef2e4a1e215aff051"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/27/0d/7c315d4bd5f2538910491a0393c56bf70d333d51bc5b34bee8e68e8cea19/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "ce70f96a46b894b36eba678f153f052967a0d06d5b5a19b336ab0dbbd029f73e"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/c3/24/9e096de47a4d11bc4df41e9d1e61776393eac4cb6eb11b3e23315b78b2cc/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "cb467c999c2eff23a6417e58d75e5828716f42ed8289fe6b77a7e5a91036ca70"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/cc/0f/e8dea6375f1d3ba5fcb0b3583e2b493e77379834c74fd5a22d66d85d6540/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "836398932192dae4146c8f6f737d74baeac8b70ce14831a239bdb1ca882fc261"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/ac/5b/df24cfc6424a12deb41503b64d42fbea6b8cb357ec62ca84a5a3476f654a/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "743185e7372b7bc7c389e1badcc606931a827112fbbd37f14c537320fca08620"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/8f/b5/853b6757f7347de4e9b37e8cc3289283fb983cba1ab4d2d7144694871d9c/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "afaeff7696e0ad9f02cbb8f56365ff4686ab205fcf9c4c5b6fdfaaa16549dd04"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/e1/f7/0a4467be0a56e80447c8529c9fce5b38eab4f513cb3d9bf82e7392a5696b/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "3f7eb7da0eb23aa2ba036d4f616d46906013a68caf61b7fdbe42fc8b25132e77"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/8e/e0/82583485ea00137ddf69bc84a2db88bd92ab4a6e3c405e5fb878ead8d0e7/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl",hashes = {sha256 = "831a62658609f0e5c64178211c942ace999517f5770fe9436be4c2faeba0c0ef"}}, - {name = "watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/28/9a/a785356fccf9fae84c0cc90570f11702ae9571036fb25932f1242c82191c/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl",hashes = {sha256 = "f9a2ae5c91cecc9edd47e041a930490c31c3afb1f5e6d71de3dc671bfaca02bf"}}, - {name = "watchfiles-1.1.1-cp312-cp312-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/74/d5/f039e7e3c639d9b1d09b07ea412a6806d38123f0508e5f9b48a87b0a76cc/watchfiles-1.1.1-cp312-cp312-macosx_10_12_x86_64.whl",hashes = {sha256 = "8c89f9f2f740a6b7dcc753140dd5e1ab9215966f7a3530d0c0705c83b401bd7d"}}, - {name = "watchfiles-1.1.1-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a5/96/a881a13aa1349827490dab2d363c8039527060cfcc2c92cc6d13d1b1049e/watchfiles-1.1.1-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "bd404be08018c37350f0d6e34676bd1e2889990117a2b90070b3007f172d0610"}}, - {name = "watchfiles-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/4b/5b/d3b460364aeb8da471c1989238ea0e56bec24b6042a68046adf3d9ddb01c/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "8526e8f916bb5b9a0a777c8317c23ce65de259422bba5b31325a6fa6029d33af"}}, - {name = "watchfiles-1.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/b9/44/5769cb62d4ed055cb17417c0a109a92f007114a4e07f30812a73a4efdb11/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "2edc3553362b1c38d9f06242416a5d8e9fe235c204a4072e988ce2e5bb1f69f6"}}, - {name = "watchfiles-1.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/19/0c/286b6301ded2eccd4ffd0041a1b726afda999926cf720aab63adb68a1e36/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "30f7da3fb3f2844259cba4720c3fc7138eb0f7b659c38f3bfa65084c7fc7abce"}}, - {name = "watchfiles-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/c7/2b/8530ed41112dd4a22f4dcfdb5ccf6a1baad1ff6eed8dc5a5f09e7e8c41c7/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa"}}, - {name = "watchfiles-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/ce/d2/f5f9fb49489f184f18470d4f99f4e862a4b3e9ac2865688eb2099e3d837a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "dcc5c24523771db3a294c77d94771abcfcb82a0e0ee8efd910c37c59ec1b31bb"}}, - {name = "watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/cf/68/5707da262a119fb06fbe214d82dd1fe4a6f4af32d2d14de368d0349eb52a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "1db5d7ae38ff20153d542460752ff397fcf5c96090c1230803713cf3147a6803"}}, - {name = "watchfiles-1.1.1-cp312-cp312-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/66/ab/3cbb8756323e8f9b6f9acb9ef4ec26d42b2109bce830cc1f3468df20511d/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_aarch64.whl",hashes = {sha256 = "28475ddbde92df1874b6c5c8aaeb24ad5be47a11f87cde5a28ef3835932e3e94"}}, - {name = "watchfiles-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/78/46/7152ec29b8335f80167928944a94955015a345440f524d2dfe63fc2f437b/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl",hashes = {sha256 = "36193ed342f5b9842edd3532729a2ad55c4160ffcfa3700e0d54be496b70dd43"}}, - {name = "watchfiles-1.1.1-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/0a/bf/95895e78dd75efe9a7f31733607f384b42eb5feb54bd2eb6ed57cc2e94f4/watchfiles-1.1.1-cp312-cp312-win32.whl",hashes = {sha256 = "859e43a1951717cc8de7f4c77674a6d389b106361585951d9e69572823f311d9"}}, - {name = "watchfiles-1.1.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/87/0a/90eb755f568de2688cb220171c4191df932232c20946966c27a59c400850/watchfiles-1.1.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "91d4c9a823a8c987cce8fa2690923b069966dabb196dd8d137ea2cede885fde9"}}, - {name = "watchfiles-1.1.1-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/36/76/f322701530586922fbd6723c4f91ace21364924822a8772c549483abed13/watchfiles-1.1.1-cp312-cp312-win_arm64.whl",hashes = {sha256 = "a625815d4a2bdca61953dbba5a39d60164451ef34c88d751f6c368c3ea73d404"}}, - {name = "watchfiles-1.1.1-cp311-cp311-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/1f/f8/2c5f479fb531ce2f0564eda479faecf253d886b1ab3630a39b7bf7362d46/watchfiles-1.1.1-cp311-cp311-macosx_10_12_x86_64.whl",hashes = {sha256 = "f57b396167a2565a4e8b5e56a5a1c537571733992b226f4f1197d79e94cf0ae5"}}, - {name = "watchfiles-1.1.1-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/fe/cd/f515660b1f32f65df671ddf6f85bfaca621aee177712874dc30a97397977/watchfiles-1.1.1-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "421e29339983e1bebc281fab40d812742268ad057db4aee8c4d2bce0af43b741"}}, - {name = "watchfiles-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/7b/c3/28b7dc99733eab43fca2d10f55c86e03bd6ab11ca31b802abac26b23d161/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "6e43d39a741e972bab5d8100b5cdacf69db64e34eb19b6e9af162bccf63c5cc6"}}, - {name = "watchfiles-1.1.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/4a/24/33e71113b320030011c8e4316ccca04194bf0cbbaeee207f00cbc7d6b9f5/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "f537afb3276d12814082a2e9b242bdcf416c2e8fd9f799a737990a1dbe906e5b"}}, - {name = "watchfiles-1.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/f4/c3/3c9a55f255aa57b91579ae9e98c88704955fa9dac3e5614fb378291155df/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "b2cd9e04277e756a2e2d2543d65d1e2166d6fd4c9b183f8808634fda23f17b14"}}, - {name = "watchfiles-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/49/36/506447b73eb46c120169dc1717fe2eff07c234bb3232a7200b5f5bd816e9/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "5f3f58818dc0b07f7d9aa7fe9eb1037aecb9700e63e1f6acfed13e9fef648f5d"}}, - {name = "watchfiles-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/82/ab/5f39e752a9838ec4d52e9b87c1e80f1ee3ccdbe92e183c15b6577ab9de16/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "9bb9f66367023ae783551042d31b1d7fd422e8289eedd91f26754a66f44d5cff"}}, - {name = "watchfiles-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/af/b9/a419292f05e302dea372fa7e6fda5178a92998411f8581b9830d28fb9edb/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "aebfd0861a83e6c3d1110b78ad54704486555246e542be3e2bb94195eabb2606"}}, - {name = "watchfiles-1.1.1-cp311-cp311-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/b0/c3/d5932fd62bde1a30c36e10c409dc5d54506726f08cb3e1d8d0ba5e2bc8db/watchfiles-1.1.1-cp311-cp311-musllinux_1_1_aarch64.whl",hashes = {sha256 = "5fac835b4ab3c6487b5dbad78c4b3724e26bcc468e886f8ba8cc4306f68f6701"}}, - {name = "watchfiles-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/f7/77/16bddd9779fafb795f1a94319dc965209c5641db5bf1edbbccace6d1b3c0/watchfiles-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "399600947b170270e80134ac854e21b3ccdefa11a9529a3decc1327088180f10"}}, - {name = "watchfiles-1.1.1-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/46/ef/f2ecb9a0f342b4bfad13a2787155c6ee7ce792140eac63a34676a2feeef2/watchfiles-1.1.1-cp311-cp311-win32.whl",hashes = {sha256 = "de6da501c883f58ad50db3a32ad397b09ad29865b5f26f64c24d3e3281685849"}}, - {name = "watchfiles-1.1.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/94/bc/f42d71125f19731ea435c3948cad148d31a64fccde3867e5ba4edee901f9/watchfiles-1.1.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "35c53bd62a0b885bf653ebf6b700d1bf05debb78ad9292cf2a942b23513dc4c4"}}, - {name = "watchfiles-1.1.1-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/57/c9/a30f897351f95bbbfb6abcadafbaca711ce1162f4db95fc908c98a9165f3/watchfiles-1.1.1-cp311-cp311-win_arm64.whl",hashes = {sha256 = "57ca5281a8b5e27593cb7d82c2ac927ad88a96ed406aa446f6344e4328208e9e"}}, - {name = "watchfiles-1.1.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/d3/8e/e500f8b0b77be4ff753ac94dc06b33d8f0d839377fee1b78e8c8d8f031bf/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl",hashes = {sha256 = "db476ab59b6765134de1d4fe96a1a9c96ddf091683599be0f26147ea1b2e4b88"}}, - {name = "watchfiles-1.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/bd/95/615e72cd27b85b61eec764a5ca51bd94d40b5adea5ff47567d9ebc4d275a/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "89eef07eee5e9d1fda06e38822ad167a044153457e6fd997f8a858ab7564a336"}}, - {name = "watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/c9/81/e7fe958ce8a7fb5c73cc9fb07f5aeaf755e6aa72498c57d760af760c91f8/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "ce19e06cbda693e9e7686358af9cd6f5d61312ab8b00488bc36f5aabbaf77e24"}}, - {name = "watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/6e/d4/ed38dd3b1767193de971e694aa544356e63353c33a85d948166b5ff58b9e/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "3e6f39af2eab0118338902798b5aa6664f46ff66bc0280de76fca67a7f262a49"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [ - "anyio>=3.0.0", -] - -[[packages]] -name = "wcwidth" -version = "0.6.0" -requires-python = ">=3.8" -sdist = {name = "wcwidth-0.6.0.tar.gz", url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hashes = {sha256 = "cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159"}} -wheels = [ - {name = "wcwidth-0.6.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl",hashes = {sha256 = "1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "webencodings" -version = "0.5.1" -sdist = {name = "webencodings-0.5.1.tar.gz", url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hashes = {sha256 = "b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}} -wheels = [ - {name = "webencodings-0.5.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl",hashes = {sha256 = "a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "websockets" -version = "16.0" -requires-python = ">=3.10" -sdist = {name = "websockets-16.0.tar.gz", url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hashes = {sha256 = "5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5"}} -wheels = [ - {name = "websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl",hashes = {sha256 = "8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0"}}, - {name = "websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl",hashes = {sha256 = "daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904"}}, - {name = "websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4"}}, - {name = "websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e"}}, - {name = "websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4"}}, - {name = "websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1"}}, - {name = "websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3"}}, - {name = "websockets-16.0-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl",hashes = {sha256 = "a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8"}}, - {name = "websockets-16.0-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl",hashes = {sha256 = "c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d"}}, - {name = "websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl",url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl",hashes = {sha256 = "a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244"}}, - {name = "websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e"}}, - {name = "websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641"}}, - {name = "websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8"}}, - {name = "websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e"}}, - {name = "websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944"}}, - {name = "websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206"}}, - {name = "websockets-16.0-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl",hashes = {sha256 = "5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6"}}, - {name = "websockets-16.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd"}}, - {name = "websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9"}}, - {name = "websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230"}}, - {name = "websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c"}}, - {name = "websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5"}}, - {name = "websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82"}}, - {name = "websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8"}}, - {name = "websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f"}}, - {name = "websockets-16.0-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl",hashes = {sha256 = "abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a"}}, - {name = "websockets-16.0-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl",hashes = {sha256 = "3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156"}}, - {name = "websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00"}}, - {name = "websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79"}}, - {name = "websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39"}}, - {name = "websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c"}}, - {name = "websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f"}}, - {name = "websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1"}}, - {name = "websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2"}}, - {name = "websockets-16.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl",hashes = {sha256 = "eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89"}}, - {name = "websockets-16.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea"}}, - {name = "websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/f2/db/de907251b4ff46ae804ad0409809504153b3f30984daf82a1d84a9875830/websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8"}}, - {name = "websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/f3/fa/abe89019d8d8815c8781e90d697dec52523fb8ebe308bf11664e8de1877e/websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad"}}, - {name = "websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/58/5d/88ea17ed1ded2079358b40d31d48abe90a73c9e5819dbcde1606e991e2ad/websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d"}}, - {name = "websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/d2/ae/0ee92b33087a33632f37a635e11e1d99d429d3d323329675a6022312aac2/websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe"}}, - {name = "websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/c8/c5/27178df583b6c5b31b29f526ba2da5e2f864ecc79c99dae630a85d68c304/websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b"}}, - {name = "websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/87/05/536652aa84ddc1c018dbb7e2c4cbcd0db884580bf8e95aece7593fde526f/websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5"}}, - {name = "websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/6d/e2/d5332c90da12b1e01f06fb1b85c50cfc489783076547415bf9f0a659ec19/websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64"}}, - {name = "websockets-16.0-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/77/fb/d3f9576691cae9253b51555f841bc6600bf0a983a461c79500ace5a5b364/websockets-16.0-cp311-cp311-win32.whl",hashes = {sha256 = "5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6"}}, - {name = "websockets-16.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/54/67/eaff76b3dbaf18dcddabc3b8c1dba50b483761cccff67793897945b37408/websockets-16.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac"}}, - {name = "websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d"}}, - {name = "websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03"}}, - {name = "websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da"}}, - {name = "websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/a5/8f/aea9c71cc92bf9b6cc0f7f70df8f0b420636b6c96ef4feee1e16f80f75dd/websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c"}}, - {name = "websockets-16.0-pp311-pypy311_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/9a/3f/f70e03f40ffc9a30d817eef7da1be72ee4956ba8d7255c399a01b135902a/websockets-16.0-pp311-pypy311_pp73-win_amd64.whl",hashes = {sha256 = "a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767"}}, - {name = "websockets-16.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl",hashes = {sha256 = "1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "widgetsnbextension" -version = "4.0.15" -requires-python = ">=3.7" -sdist = {name = "widgetsnbextension-4.0.15.tar.gz", url = "https://files.pythonhosted.org/packages/bd/f4/c67440c7fb409a71b7404b7aefcd7569a9c0d6bd071299bf4198ae7a5d95/widgetsnbextension-4.0.15.tar.gz", hashes = {sha256 = "de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9"}} -wheels = [ - {name = "widgetsnbextension-4.0.15-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl",hashes = {sha256 = "8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366"}}, -] -marker = "\"docs\" in extras" - -[packages.tool.pdm] -dependencies = [] - -[[packages]] -name = "wrapt" -version = "2.2.0rc10" -requires-python = ">=3.9" -sdist = {name = "wrapt-2.2.0rc10.tar.gz", url = "https://files.pythonhosted.org/packages/40/13/fd5226e965a6c31ab6b9a6c703e2cf29a0ffab8fa3785dd9cabe371d4f68/wrapt-2.2.0rc10.tar.gz", hashes = {sha256 = "654334906fbec684efa5fbd3a0c8753f128a9db2134ebed87d5b10768b799a1a"}} -wheels = [ - {name = "wrapt-2.2.0rc10-cp314-cp314-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/5f/93/86b3fa8be60b03f9b06af060ed01fb23b881f9349f2f64423b36f0bcb6b5/wrapt-2.2.0rc10-cp314-cp314-macosx_10_15_x86_64.whl",hashes = {sha256 = "8f81ac6aa1183d158cb6ce3f0cf8e67edd601af99a5c0c5729bbb188a548eccb"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/95/61/a031db81126842c222a52a20b7f44ae7dcb5d29604a11dc82fa9702a447c/wrapt-2.2.0rc10-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "fa2588aaec955021caa7f6fe526a3db8418dd9197737c036f1402836982dbd31"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/8e/c1/07b15a0298060d3b749e99724e7a23a8ee30d69b846c84333d95e69135d5/wrapt-2.2.0rc10-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "0264dc31acc543e4b186ce41ae8374d40384e97488d6d616b4765839008ec4ab"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/60/78/e88bb8f79d460585e1aeb3469cd2237c51adc5a60bbcff73427eaef1d9c1/wrapt-2.2.0rc10-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "81282653edcfcaa8b05f35692daccf15e1d47690cd1d9538d5f6937b9cb3fd0b"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/e8/d2/36c7abda986d21267ac43205d68f8ad25d3d5a16ac4492696265224fce2d/wrapt-2.2.0rc10-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "2be486e8cf121327eb6df10c906352218136fd54c6ce7ea5a4e35e0af1a1081c"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/44/55/6d6f83545cd3a50384e4868786a6a140a1fc114e3310f3cb72db6343e3b1/wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "69f304d6ab0fcf74120e85d44f416f11258a72f410df4570be9342c01823224a"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/ac/ec/ef72311b88a758e01ab471e368912e31c32cb2a1c674bc25553544a172e6/wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_riscv64.whl",hashes = {sha256 = "c2316cfe68080cacdaef29f1da9b61afdc3c3d6934c9163aa4110523b2e1528c"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/61/4f/16ccb49177f7e73808c2ac27f87a5373226cc330cd7a356e7f82ed72d4da/wrapt-2.2.0rc10-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "d2873fc2e3b33170ef4e674e9d1e94637a8d104a6161234ad0dbf1918a5bc5e5"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/f7/14/43d7969a06d97091cdc418a67df86d1d29d466f8903a933cd3851e38ab5a/wrapt-2.2.0rc10-cp314-cp314-win32.whl",hashes = {sha256 = "97c123982cb4abb9799c543faedc9cae4a7f6695cca013d4d8fa245e5a0b5e5f"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/2d/fb/effded00ec679fdeefc060b7119c0d02c0a420e3a230ea02cc2e088a725b/wrapt-2.2.0rc10-cp314-cp314-win_amd64.whl",hashes = {sha256 = "800d0da73858e61ff32e30ed12aeeec2d51c816bedf3619c05f78905d09956cd"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/88/55/5ff81420fdddf3574458e9d1beb477c3bd860b2c9c02b0ba49f22bce9d11/wrapt-2.2.0rc10-cp314-cp314-win_arm64.whl",hashes = {sha256 = "579b96c9850ac93ac7ab964f37045e36657e6348c4c14181f7792c9f38a30e80"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/4b/31/5fabfc6749f67d7f4b9f31e976879987a2cc5f18247c55490621bda7654b/wrapt-2.2.0rc10-cp314-cp314t-macosx_10_15_x86_64.whl",hashes = {sha256 = "974138642610c4bb7c24edc1b8304a9c2eae53af42b678014a8414113aa5d166"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/69/de/679d843b0247db8cce17c32d1d7cf718b0cd1812c99e0cada9dd7150a37f/wrapt-2.2.0rc10-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "4ae962f92725e3e4f7d6711b56d53f525463c7cc0256a571fdc5115eae46641d"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/8e/d8/25400020518cef71544f02397c3e1282ebac11ffd68ffc9aa7797b0249a3/wrapt-2.2.0rc10-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "717d2d3da21ddb8a74d83e7c453b8b0a498883785e930c3a479a2a20f2e09746"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/01/b6/8b2788f70827ab17aa13ad2194f493fe69f203adea240567ca4e273a50b0/wrapt-2.2.0rc10-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "1ad1ffbb60ead11d9e014de1674b4a7922c1319a390a70812255c83f88d41782"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/ff/04/9675990b320e532a8c3f71ab1a881e416ae3d71c63ff707e5d853d9d2b4c/wrapt-2.2.0rc10-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "30b29f51d4e1ea12bd9ed8d1243050b7bec0bc012bc2d61bd8597eecf2b64772"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ed/54/7e42c0e51b6191588a14a7805129f0ded9f4e90da1cbd53b708e80096029/wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "476587d75363ff7b789e0c778300154c0a8cf741774f3ed953fbd6bc44d88d18"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/05/e0/1cca6bf14783228e1d6f0904fada908e2ce392ed789fa570a8f24d651eea/wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "6db5b52799a3be5da639fdbc5a58669b033d6f696e58284216b229cb1779c144"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/cd/d9/2ced8e598e455264d6c97261896f2415383789f79ec0117f5c07ea33653f/wrapt-2.2.0rc10-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "7941ab8fc6460d2891a85dabcfaa1b2fb047c60c713f8ae87b455ecc9d2d75b2"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/52/32/b48789ff0ef224136bf1d4d26cb19b88fb963dd067e73a285eaa4fe8c7a4/wrapt-2.2.0rc10-cp314-cp314t-win32.whl",hashes = {sha256 = "a0c26e62f8edaff22b1284815123c851eded22f56c8ecdfef9c29d6571df8780"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/00/42/06dd084432d2137e104c1536616769d3fd19bcfe3e2744b7bfc5153bef45/wrapt-2.2.0rc10-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "ec65618456363f1e0530d362bd9ea48541494aff576370d9e7523977d67e37e8"}}, - {name = "wrapt-2.2.0rc10-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ca/23/46d71ac1f8797cf7197bcb034df656ed64d77c1ba04b688aae4187d3c7dc/wrapt-2.2.0rc10-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "37e1e4a4c6900ef832069f648e4c0c897058fa333000ddd73de91c42f05ba8b5"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/0a/a1/629b4fbb4e372206aa1587a5dbbbc737f50d6e17f8dec10f4505b4a18c59/wrapt-2.2.0rc10-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "8d174cfd2234f9695060693b05d0cdf4a29c7fc58a3896805de1f06df5e17678"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/91/19/701c35fb8cf379872065c4a113f1c55c71150a1b8535bd87afbde8153bf1/wrapt-2.2.0rc10-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "eef11c5defad6aaed70b1a332948b02d3eceb14e9cc72c485c97b3007aff2a89"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/e8/d4/c39c269e08d61cf2d2006646c876bd756ccaa648277f32ae55888bf6b187/wrapt-2.2.0rc10-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "64ab66a4f93c54fb11deff60470ca90ca95dfabd3bb7799a749aa0685783854d"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/21/fc/d36a584ae61fe3fb26cb0ce751ff852f2960bd7eeef8165c7990a1cd873d/wrapt-2.2.0rc10-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "e0cf656100eab1193c99aa72fd5cd1906806396cb8f2ad47fb321128f2792fb2"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/6f/87/0748c676183e9043a35d85a665550909538b802b8057b97e56d2a11ecebd/wrapt-2.2.0rc10-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "452e3d297020447c7fae98bccbd7c4143b8d2c30e3a017698d85ba4130196d20"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/fa/29/c33ca4d544c7a730a8da0b1bf29fd142a5aea4c6d684c743c8686926b10a/wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e52c7612512a1b85a297e6faa0d37d0671ec578267d9ba5f3838f64c033017a9"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/5a/af/ffed7aa7d6fd82bf5d4d1a76f28ee731a190c59b2a8e1ccd48bba9168f16/wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_riscv64.whl",hashes = {sha256 = "4febff8cf99312b1dc8ae92c5bada78a6c4116d72600960b9e4f85d7df4c5d6e"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/cb/ca/59aa3a8c43927648ca87800ead94077959bd743f749fc357d416d619cdf7/wrapt-2.2.0rc10-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "cc8b26679584ca894a8868dc12929a2ef5ec8ee3b0e8024a590d795388622bdb"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/8e/09/e7dfd67f78c461b77c086405f634159a3afacc332cfb76f137161f347b79/wrapt-2.2.0rc10-cp313-cp313-win32.whl",hashes = {sha256 = "8af9d7975322391bc02d38d1a3da8938dd6156136342305871a393ab0285e295"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/2b/07/0f54ad28efde3904c2a591ee930ef4152ae6f845223374e2934b67aa6eab/wrapt-2.2.0rc10-cp313-cp313-win_amd64.whl",hashes = {sha256 = "17dc46e6d4694d5d730beffded21bf2bcebe37524a70a830848e2a8f47b59ddf"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f0/64/1c40767fb1927407c4d83d0369cf33402ecea1b22319172d4f31e29f0e0d/wrapt-2.2.0rc10-cp313-cp313-win_arm64.whl",hashes = {sha256 = "fc66085eb491edda8212d4a0ab099bc63d3749ded586bb7cc8b69d85920a0b6d"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/67/26/7ec58ba818330401d201f73da511be833378513882aa8540b5763b3e6042/wrapt-2.2.0rc10-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "29757c68b28beeb067069ee8ee01035d5d954d093ad25aaa44d4079370886882"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d2/18/d960682d6cf45b2c29bcad2044c91460b5b6f3394e573db48188a0f18c3c/wrapt-2.2.0rc10-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "1bdba361bfaf684d075a216dc6fc0c1adf275c53553df963c0a83f4495f3e243"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/0a/6d/04cf4993a3ace28ae04d017b8ad04fdd5b3df94f20517f48fa02c98e5463/wrapt-2.2.0rc10-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "e2e64bb4a3949cb0ec2f1f11f7c8ec97dba6c70876e2d3351603a07cf0efa372"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/6b/83/f2fc1c2f29e95b2a5dc407119223f6d20e150a25b4ebaa79f16b58b870cc/wrapt-2.2.0rc10-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "f9abc7df75292ab960a751e40efce1c962b617c647058b727b97ab70036c56ac"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/a6/ac/91ab7fa8745960a5fe0a5777ac5c0e76ff8c82ce1a9455c22cc9f9d882c3/wrapt-2.2.0rc10-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "e7ea341d4a88193ba9b5a72cbb8c5959ca151b4b71c9dea999c49cf1d9735fbe"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/21/c3/516b870a4e2f23246dc933683d127c5096ad198492b2ae5734aba187fd40/wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "97f7e7e247f5004f318635ac37e6d365262f62f592b7f3fefd34f169000d41b5"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/0a/a7/faec7698cbdd88a4c1f7acdf74fc7c66af7f8d18e9142921a3fcffd60345/wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "084384abb5e3e87f2a9f86ed5b6dedab62c9a9ee5104dc6e49ae42e22e68d108"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/2e/e6/7ad025be96772d87ac9227a35d129410cdd1b2d3ee993c45dfeacd0e5855/wrapt-2.2.0rc10-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "58d0a125067953e4a5486e3c41df551272aac8e98b919c6ad53972703be09675"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/d9/9f/c77fae78d2b5f8b441e4cb04d6377541bf268448cbf89d896dbad3134c86/wrapt-2.2.0rc10-cp313-cp313t-win32.whl",hashes = {sha256 = "ca33bb46a378620b4516dfd633aca279d1241afd542ddfda88ad42991a3bad5c"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d6/94/be15062160ae0783f1aa557d1c0aa823670ea9ec5899d8a575c891dea8bb/wrapt-2.2.0rc10-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "d7447f944dd86f4da04ac2df5e82c693c9af5ffdfc1894346cf806453b02ed2f"}}, - {name = "wrapt-2.2.0rc10-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ac/27/ddbbf81fe4915ebf8636938658b900102dad46d2eaf7041bf8a47c7ada63/wrapt-2.2.0rc10-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "f92832640a60e6c29445a65c2b82f672c458fada5de6f194e9f10d107efb8f94"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/1a/22/d6fbc4a54a46dabcea3c942fef82a6d4ecd68aca4e1f69a00e974157bcf0/wrapt-2.2.0rc10-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "c3b518b98cc711ef9b7d05fe44649b7da9c0cd3c9e60a826abd909c64a772668"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/62/fe/682c9351265288071332b65097c0c024897cc6eff183810c3fd76d7502c5/wrapt-2.2.0rc10-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "6d7c25fd90a0086e608a471a4c9e66855ebc3d143dfe31bad15ddf14338e30d3"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/ef/63/2df839d761645835263defa924a548675bacec5521b39498ed5df0901cb3/wrapt-2.2.0rc10-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "21a489d77869b7d030172f511142e140f4dfd4836a2426d0e26d2c913722fddd"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/c7/e3/aef5a0d55e779a30d07fc9af50bb3b504812aa8fa211461d2650f6c7d524/wrapt-2.2.0rc10-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "1664ec6d2f097548e45671c2171e485ddada066f89e1e1c599b208cf8693600f"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/dd/09/672121e17cea4c1c40f4ffa4f4aa3a19f5d50cff10a758602315b0029cb9/wrapt-2.2.0rc10-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "01913da074818dbc42e70155f05609f89d7745679a1938b1bef004b506defefa"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ba/df/00067f0faa27101bd04925e5e9db3172c43acf51e0d784b1c28d8ee0faf4/wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "26f50984cd44de71500c101a20fa9112c2577dd0b90446d3b1c24c64ab50b600"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/a1/f4/d006c6cfc3b17bb30ab0178c3b8905b029c1ca8d0142e548658f896507b6/wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_riscv64.whl",hashes = {sha256 = "5f0a7a2362e41d57cb99fc5fda425a7652d82bd0f4099ed0f4d224867d1f651c"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/8a/98/8831c1687a89f7e13b554e30d3e679c6d17a91d38d66907764037a5e0d87/wrapt-2.2.0rc10-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "4410420729a63609c024d46368f03cff89b7d041dac8f6e45366ebd8b9d105aa"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/80/4e/5a58deecf5dc280f05ae77e088e728119c6b0d6e1b18a13b64ff9b794364/wrapt-2.2.0rc10-cp312-cp312-win32.whl",hashes = {sha256 = "6d5831bb3a05f7762fb51b519a329b17fd017ad7912b55727595d23a6b324a31"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/19/2a/ca0d3bab3a000b4351cce3ff5fa5343e653d8ebddea9cd41d4582be5d658/wrapt-2.2.0rc10-cp312-cp312-win_amd64.whl",hashes = {sha256 = "99d6725ec57c96e0de76f4b4005a89e3af166dafd1f0b40d2918a7cab1438811"}}, - {name = "wrapt-2.2.0rc10-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/9f/d0/13240f73f3515823a7581ad4ca0473d66ac9fe5bc5f66686c1ec40c4e8d6/wrapt-2.2.0rc10-cp312-cp312-win_arm64.whl",hashes = {sha256 = "dc3822c3cf5d11566fbfee24f0ed6e5d9a95a9f2667484b4239f6e5472078c09"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/32/5b/6e04a6fd699e6dc6c8e56725dfe4bb286a610d3b35aed6990a023bb89baf/wrapt-2.2.0rc10-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "3d61bb93dff6a605bc9f74a9c80e1c43449b939226c568403145ec2422996e4c"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/41/bf/060f27d7f35e9cae386c2d09d9e71731c9ce0afdcee7e48a8dc00f5d0623/wrapt-2.2.0rc10-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "fdce1de40216df2505d35fffc47ca52abae3fc94dd452478afa28258c1b1a6f5"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/b7/8d/3112c8f96eeb30283d3671c665823a5889b64bffae24d81febefb933fa94/wrapt-2.2.0rc10-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "c82c40e86a92e20576a6263799f3adf81e08f9162d8119ddc25e6d413482afa1"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/9f/8f/6c07a1a97723b055c1fc108d0a4ce4779986ec3939c953b6a18a1ffb4c00/wrapt-2.2.0rc10-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "582c49501f6feaa063a520edde2b94a7dfde231eab981cf3ca1b689b16d629d1"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/0e/43/263756369c58bfc8f2c58e27fdc21ec11e81780cd041b92d6384b3dd7373/wrapt-2.2.0rc10-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "5ae98df99924c5f9f6f9bdf0feab765d2ca848041d39b9f758eea4cd7c901535"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/a6/7b/bd0144efc848c5d600832fe68be8ecdda1151a1b580a295da5d6d86cc6a3/wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c10ef47939db9f7ba35aa371dd194dba468d0ec56273108a7e3cf2df1ccd336a"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/4e/a5/4265726936316449ba965adb9c3676c01322d43d6c5f9d261eba6d248657/wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_riscv64.whl",hashes = {sha256 = "c1bfac44eec4adb429f90a80a1911e9efe3a6b1159df92d410ca5ff06bb85d7e"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/1b/3f/b77d21e2bf08daeb591861fa9bf13b844144c171cd2a1ef7830225b9b002/wrapt-2.2.0rc10-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ca7dc63028a782803b82a98b918f055f9210ae20691ca233378635fa3371ff4c"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/15/93/c149a4c7ef6e644a54c618623563db5b22021314ed134f52c615fbb58a5d/wrapt-2.2.0rc10-cp311-cp311-win32.whl",hashes = {sha256 = "e56c1307b8a53e5eb10a66f1a911de4d50dece6aabf8634d2a3dd0a081872948"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/88/d6/7445898124a66bcf19593a47ca6020e4a75bd29a293920525bb8380a9eca/wrapt-2.2.0rc10-cp311-cp311-win_amd64.whl",hashes = {sha256 = "6b47ccb8f33515af16a0cbdfddfa9c36a706de12956c638f24143ec08f813304"}}, - {name = "wrapt-2.2.0rc10-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f8/06/dd8768b0ff6fa2fd330c7709584ee6c9ca70ebc67fc4dd1244aa99569c11/wrapt-2.2.0rc10-cp311-cp311-win_arm64.whl",hashes = {sha256 = "3f093505afaccd298ed4c8408d76b8ec99ac064f505b15b9dc761635ba9af71a"}}, - {name = "wrapt-2.2.0rc10-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/0e/05/a900f438141dd89f13cc9e996a8c75498d3ade06c3116bc935cc4db7aac6/wrapt-2.2.0rc10-py3-none-any.whl",hashes = {sha256 = "da196d360b9e8a1fd8af6a484e581c4e6c20d5c496c4001983156392af28c470"}}, -] -marker = "\"default\" in dependency_groups" - -[packages.tool.pdm] -dependencies = [] - -[tool.pdm] -hashes = {sha256 = "86eb729d27e9b8244f414b9667b932d8d485f9297e4ebe5d614b2a74fbf5dce2"} - -[[tool.pdm.targets]] -requires_python = ">=3.11" From 2af87e7c0183fa4de5869e447c8a580f16e4a904 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 14:24:48 +0100 Subject: [PATCH 30/34] test: a small fix in `redcap_data` tests --- tests/unit/test_redcap_data.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/unit/test_redcap_data.py b/tests/unit/test_redcap_data.py index aa261ed..9e07a8c 100644 --- a/tests/unit/test_redcap_data.py +++ b/tests/unit/test_redcap_data.py @@ -53,22 +53,22 @@ def test_load_units_conversion_table__from_vertex_github(self): class TestLoadCountriesTable: def test_load_countries_table__from_local_assets(self): - with Path(__file__).parent.parent.parent.joinpath( + local_assets_csv_path = Path(__file__).parent.parent.parent.joinpath( "assets", "countries.csv" - ) as local_assets_csv_path: - expected_table = pd.read_csv( - Path(__file__).parent.joinpath("assets", "countries.csv") - ) + ) + expected_table = pd.read_csv( + Path(__file__).parent.joinpath("assets", "countries.csv") + ) - with mock.patch( - "isaricanalytics.redcap_data.pd.read_csv", - mock.MagicMock(return_value=expected_table), - ) as mock_pd_read_csv: - received_table = load_countries_table(encoding="latin-1") - mock_pd_read_csv.assert_called_once_with( - local_assets_csv_path, encoding="latin-1" - ) - assert_frame_equal(received_table, expected_table) + with mock.patch( + "isaricanalytics.redcap_data.pd.read_csv", + mock.MagicMock(return_value=expected_table), + ) as mock_pd_read_csv: + received_table = load_countries_table(encoding="latin-1") + mock_pd_read_csv.assert_called_once_with( + local_assets_csv_path, encoding="latin-1" + ) + assert_frame_equal(received_table, expected_table) def test_load_countries_table__from_vertex_github(self): with mock.patch( From 5b22f2634576734c4646be98fb7eea9654d37ac3 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Fri, 8 May 2026 14:25:48 +0100 Subject: [PATCH 31/34] chore: fix test workflow badge in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79ac7f5..3e0151c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![CodeQL](https://github.com/ISARICResearch/IsaricAnalytics/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/ISARICResearch/IsaricAnalytics/actions/workflows/github-code-scanning/codeql) [![pre-commit](https://github.com/ISARICResearch/IsaricAnalytics/actions/workflows/pre-commit.yml/badge.svg)](https://github.com/ISARICResearch/IsaricAnalytics/actions/workflows/pre-commit.yml) -[![Tests (python versions)](https://github.com/ISARICResearch/IsaricAnalytics/actions/workflows/test-python-versions-coverage.yml/badge.svg)](https://github.com/ISARICResearch/IsaricAnalytics/actions/workflows/test-python-versions-coverage.yml) +[![Tests (python versions)](https://github.com/ISARICResearch/IsaricAnalytics/actions/workflows/test.yml/badge.svg)](https://github.com/ISARICResearch/IsaricAnalytics/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/ISARICResearch/IsaricAnalytics/graph/badge.svg?token=Q0A84OK6E5)](https://codecov.io/gh/ISARICResearch/IsaricAnalytics) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) From 7ac5ed8cca6af697d1ac6e0504780396bf7d66a8 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Wed, 13 May 2026 13:35:10 +0100 Subject: [PATCH 32/34] docs: a few more improvements for the conf and index page --- docs/_static/css/custom.css | 3 + docs/_static/isaric-logo.png | Bin 0 -> 10177 bytes docs/_static/osi-badge-light.svg | 142 +++++++++++++++++++++++++++++++ docs/conf.py | 35 ++++++-- docs/index.rst | 7 ++ 5 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 docs/_static/css/custom.css create mode 100644 docs/_static/isaric-logo.png create mode 100644 docs/_static/osi-badge-light.svg diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css new file mode 100644 index 0000000..b6b14a8 --- /dev/null +++ b/docs/_static/css/custom.css @@ -0,0 +1,3 @@ +.theme-toggle-container { + display: none; +} diff --git a/docs/_static/isaric-logo.png b/docs/_static/isaric-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c5e83737e08ef9f6eb11f1170118949be8d88b7a GIT binary patch literal 10177 zcmc(lMNl0~(5`VO_`x+ehu{$W;1Jvo?(Xg`!QI{6-3jg%+#$FJ4|3rD?)q-->c5Mb z*>u%Z&D+&o{mdJwq#%WkLWBYZ1%)mnEw1w4IsShZ63l-)6(8>e6ck;AjJSxJXU=6V zVut$2%ja&Us{L+v?_y~rt^|;t3LBL`xoBanC_tyCafGP&wmcG^s|{?TW{ZW3*I+1y ziJPKd;;?J>w&VRe{hsf$8a#EqJ>@*t1iW`T>YTgIdG0yMxtZ?ausH6eGC}*EqZabq z3Y)Woj1L$CbToW#`xQ3Q2>%Tj$Lwh2WE+GUZGx%`Cehg&{Idr0zY}r}B^pt6V?+03 zGVFH+nj31V%J-V{b+6M|Od0TV&U`mG7z8 zeM>l50Y425LI51H1V~Olc@&rT2Empx+2*u17!T9Xgv{0oT}JJdGx0H+Giv{Bg{S?B zi-b@H)iy~~M4Eo$It)z-^z(7MKjO$SbJJf=@vpG#Fh)R@++?1hM<-CmG9v2d`eul$ zwZ_`DeFVva6$Nip)v8F-ffy)oKvlNC0X4SmC6{ja5c3{*Y0w%BYamwts?&6Zy@yx- zNg!sLG?FAPED|OvJv`I^H7VX~$A#~AFJMFjbXv2YmZBaV#vqbR11KWRx_9DOh4-J`?hk*cJJ&H_Lm626mN;*z*N98M-N%h zLSJWQ{Z<-Cy>WvUg{&RbJw+?Xk*90D`aA1!BkNthTaU-!>D_ZbiQ|e4{nY9i)+i6L zqYI~iPou?fpuJOLyA!AdER3!G__jmETsSL>t$qJNWhnjcq5ImghQ}ESnW@8BRo~6T zaKB1HHcLHrRw5g7{xprTx2jO5=faMJb+AY+`_T;-r+0`p+PP#-W_ETJ#jSHz;gS zNrCVu0XR0P?nBy*%Y~NIA9YzUW=KdB${aA{e|H?`P9gQKHC2)?(T^!3oD#+xq67)8 z-qq{4DbDQvKygA=Nn|^(3t50Fo@k>2rue8U9E{27Bg-J-GvXpPIx3O`Ad(dObD%MR z;cLu@wipNrdQ=WXvG>nHoDCrcb5t&=l3M9!g!5v9EP^tqDS{d+l0cRUz&h9{hAHVp z{(S4VDeL`sjt~vbD)en^GJD<5phV3;GK4k>WJ7qKkc!kI6X#rPkegZ38RW!FZ0E@e z4>Cy#S_v|GzorO=2S#)5B#m@UfMp|;FDw8!V(-56AHvZXbOE8G@I*|r1f`rS0IC8Q za{^`D_8=_mhSLO^av;Ar@61>8*92A3q)_q1$ZwZU*;e1a&M7tvj$fn*ew(;(KQ^0O zCoEbFl7MzpT-x(z0-|6lOY5PchXUnQFLY9_@D`4t>=#0hE0i?ihxpiW#UlUsO zfpDxO3IjA9x%yehj=bAz%pB!`58)o75y^^7#vR2gGvNrRQ^z(A69nTI8&h z=z-t}=3MhKe6caB?BT$CsA%Ha`X(}7=Iyr5nN-I{qpnF9jR&S z9##$o#5}cx&Qzs^g-*q|f=067C_8M8!m2J6s*NR&43~0_(A*|bg;7*-ZiAK`&Jf*{ zchKs*m@r3aX6E&FXp%1bL($|XdJ(L1;@r{X9cqzY)&=2U5mc9gD~GPCLAP-+nA|y? zo6kl&q72UZeDJ81-AG>~4Nl}bS@sKQ32s?2XMH{E*x55Owy1r2vjep0+W>RO{Qa^q zG48Jh3W8GgM{O}2DmhKJ(mpLaBxzL4cgcBfsW=yTdl{c<}-uB_mJ-#^qe=<4XXY=}jv*hq|D6FxqQd=H%m z3Si6(zs%gdzTtV@H^co5g@^XGR$EwXL;{DZRKZgX+z}O*Eocz~+SLw@m0Bu0-DdzY zTza_O+hlz11uMe*e$oM&_Hl0o#+*e2{H21uC)?CO8r+pOHQv5$^Q#Ip%~c8RYsaN9 zkn4GfbD00S*H83hh(9GuHX4hu7TLrJ0LLD3P?84zhaV#f5;=-Jjza;c6Rq4tq%D2- z;6$Dg`8t>C?idh|->2ae=QPdg1#T4PsaDN?LW)-UjTy7F#8baP1>B8VxhhajMFG2e zttAeP{~eq*@*`b8GwvckDZ5FYPg>*+6;&O!v~7ba9LG4)mZ@#=EXG3DD#P-L^Fyh* zMJy-hU0Ur|nw(mLP?pJohg&QqLi(&_9gi?3U!7}Pv>*7I;|ac<;9DZ%7k=;(4k7%o zxA-wTvaYE#h2l`J=CKr|V-1#>fsq7)%~)Qb(^VlJ&( zcy~tEX{YJv%;B#3GcKfMf`J`y;`Gh^?@9%a7&2w6h|8mUv%7`mw!5DMp^3)m zxc_Vj!gXf@!91wL|2Av9sMXo3)Qp|4Cf{KzVVX^>w1~u!-^@Nm|uJmAQY4`0L4hGzPutg&Qr{2m|U;(~ym z1cMQi<{Pa76(1%5wwO}sW#V_uGS`e)(>o%@^mk8+S(#15FV0Vj8z|A*)J@hlsxqnV zEfN{7(#IWz6i9Egg0ml!EQ9Rof?b8cBJr)FOJQHjKbNK?3dTwo&R>{{80DcI+`~^@ zZfw$@#9U=J)c|!h%WZ0WE1HoZEN^b72&Q3C$iIqtBZWut%D<|NDr{39<23u2+@i*Q?WUl>_M2*+fBjK!SlkAt1QM)y3{^}9&t@1h7gG71^2Nt#0kuy&|#E@3SlLR81l%t;>(9h!N zeKFROl$B`}0)rZqLt;%Y7iM)dCK`7FqwT z#Kfd>5cKyu$zq(-`xE#irBR_DA3GdJoP&y3b|M><_=LsHu67uzZ0ziHbA)#_C#bjg zFP?QgCP4Yo(X4g{x1{PzicvXr2Wj3P0Zk3bIjs&Ux#qL8=b?Z%3~}Zh+Gb%n#;#X6 zuR~DF&-#X%QN#P1xzvCeGk!)h%%$W}++N4#YKK0%xEsPHs`FXN*1ic9*Km+CUruM{ z^&koGdc9_`4@ZN($`)v+-vvGMIa_4|YMtRM!k(gnVh5;|@6G(E>zSe*CPWF0q6qQesAO=zP8bIp86m`|pvpl*-+Iq?CO6Gx9SRts zT|Xh~U`Ji|{4u({3bVEkznP8ZsLyOGUvB?Owd-KtbL7?IS(|V&=k+Y)^-jsamMySE zHTrW`eeQMo{)y@bvRTH+b7%`~EP`PMB^+m;-4{4hwt>=*{fa*v3MplzkvM%T7aB%Z zGXwL@E*BsC!nGyqqHB~!1l#cn1ern|`5D*A&5-Y#7)8=UQTp4zaMf!a)HH2FSXQE# zp+&)9Ny2hcrk%gtIk&~#cICBr%GKZUp&eL6zDBv^cdxrmM=Wj71xe44vP81@mYlr2 z-(OD=@C&p);mmh9Cw~Mu(BG#+fBgcbd^f)UyTsJl2i0iG)B^0{NBTj9ZxXxGL{S{`6LF%N>Ir{5Z z9-%_?QvaRP-mwKuf3@Yu&|O7PTaFpNrE14_>q&#wSy^jJp>-q|s=EB~x6~|>KRV6q!CA(@0{Y(PS zI#Zn8hIHDCm>rO?E67|;7|vw49`>tsE&A*S3}wkj5Rc7YWG;)(Z8QlxL41>%qen%L ze+uhfr}+=z03F4WI;M5sX)Z2H<1iPMW%%dtH2Z=S>VWU1oDVaj8^Sx9U-QApW9cMb zdY-Ch*CV$0X-&ml-gh%Px3{G~^>^+TRLr$~tmdm~>U(Y@*>{&}Kdc@Vd&g=7I~aV# z4QE$3_2@KnU05QmxpRxI2zMb>Tl}r>H9i?TsZr@m3_=E-#e37(zP=O6tK$7T)mfFk zy=|8j)v~w9I?;1q{2PmA46g7rJRj4Vu<+CWDO7eI@XE>@9az1%`>l5{F%9EP-9T8l zR6YqFuGCAzPEzumewMl?S7}!U93->P$+X7LG!1!9A<9l}ss4CZwI=h*y>vs5=Q=M_ ze>^45?p0+JR3#SH?YhXf#Z9||9486&vygi#oDP|}ukmDyait6DGAh))O*Jq57_fUK z#8#gw`zZC@%AYP%LYblUu-|yt%P##;9hwS|uHB!1lby<;b0Bxt=Uk=~w_G@H3OY&S zQ$(BjI6pDipaGg~$3;=%+YtuDHdStwsSeN2xs&k7?@z_2pG7G=|H$YLUb9+eCSFrG&Pug9p2FnJh)iMvV zSDiC`=`DIF(ZS0;m?sG3n$d0Ga%d%Svo=)2%zX5aQx-7qjS}jR{{Cem`OqpSn?gb_X z<~PCX*C;2=q>40eBXvR6=EHHDn5@wh9R)a}nYp=bzJH>%-u1J@dM);lHCeE@e6EFF z`Sn11o58~`{Y;9Q*A)x*n12E0y%0Sql4_xbtNE!adr$U}!6^Sm?(*?`5Yl$Xx+8MQkOQ%~X9 z&Vpz6v%ikiUSj!JSUC6P@Nsrvq|%)kt8U+q1F-480uRX3*ABGtWyk{}xN1N;nj2vzAsDksw6U)FUNPwYZlbT1 zQsr{sh1#QyD!Y&DfON(XJ+bq2p3_&CALQO9iWo8eZy|hL`TYI&aDv-W^tigdKh~$n zug{!HdJ3NwZ|=x@N6FgxV9Tu&q0DCLee-a6SVQbEdf84FsvD<_iY<_3VjGH>+U7~>ElRHHkCH`k**|?> zXYrp4(k@cbl~RH@aQyObgoZtKhNC*8lUVB2mc8hm$+G|83HgXK{`VF}N5_9;736~| zarYUg)8Yy1Y^xQTd>6Y&B~IQ)&C9#uy6MN@*=1gBG_%OO=}vY~?cA$yR48ip+I~0~ z*zXkg6B1vzcV{H(l~Ok%KEY6FYi=Xzy6b*Dz)BFR=e z%w{-yGUmw81h1yLk3%(A-a7=Yh+^%A`mNhght#u5aXgs*;GTh${Tocadal5E(g3Fw z?W1`pMyz{`@fd?T`Z^blsf)Z&UAjk#dqKahKVHPIe6a2f;pXRJ-kvPdhyb7&hT^JY~?l? z;z;^S>7u*{P3mIENc66P_Yy*9n_#Phq%n{I&)@u@%!-<&EcmfaBS-ry8@@Ks7eMGJ zqcR-zqq5T4>AQ)yWyIsxkY{9&HPm7m>MfR%$@bysXbgWYiK&g~0ORx?aD!aD3I8t~ zmoWKWm1Y%QeZee`7_+5CSXcAVn{HR&UB2h~(&Q~hWuvEF^vEo}AcDQcOGp+FpF!0g zDLz=G^DfBX02Ph|GjTDI@2}fEQgduLbTSq8$*fUjlS;~8X`~z~u%200q& zRsLEii}N7qB|qboJ|QLlx7SbVP6}(W=FO4;RqDWM2#SDpSV^Fe05*m|EHFaV^#4Sk*8RUS>IcqQ)2xS-y9vv64D*j1(Atz>da@YEMta_r1y_BI~m6I|S40C^I zW{!JEWD>r=OP(ocPVn^5##s`1+&HP&A2g#ALeK=oi}=j6_O6oc`ge(H-z$2sy>Hz8 zvISFRF;`0}4wL1#Tfsr8rGQrk2PWOz1!AQbI+VS;|I5bHf zTPrdjbPn{ONLq?d;kmhv;(I}SZ7Vkj)BP~Mu%uHa&c^h4L;hp+iUYI!t# zCioY~N>YtWNN?qC8rb7l{dc12yw(i9`Ey^u6?B((w(NHP)df?GdI{UhJnk*>B1r&~ zlKSf;f%&Zj>YxZOe7kB06x*OQ@kdXefn3xN!yn2qB*3UT$^ zZ`zyh3&!uG#*aM#2(x^&&jV9}g0xdt`bn&@)P@M6?~+u|8{D>qrPcGh7Qqtc@jG6-_laXdj#rj7owkzsiew4Se6|D|8v&0dL~7#H6Hw=u zVXt;4{3yvfcoSeb%|>g?i^rT1-rq;6e;%pB;r5`V`(J`LPAnKa`b`;zMIsNnndL1$ z^?aUpE)S&IEigmDLvhHMXxP{E{Kh04xOE@*Xt%8+1mdVh)0pSUVb{GC|1KxiAQzhB z3Wzyug^nAI3sZBJJ+Dqr{VY{0m-Ja~@y`i@75;*0q5E8-z%sfgRrzgrQEf7>R6=Z+ z&@xg8llqnQ_Qh=fr}kXuSawFIrk$myuX~a`Av*eTzzKVU9IYXgl|{$x*>iF)Ev^g7 z2$?XQg%LT1=4M-kl;hOhRY|qZbTvTDWpC05 zzSQ*K(A8Gx(~c$_greW?(icf;BI_Y~bkZ6(>+6+vK%;dMBJzBJ)liwshzQJRY&N`# zRg^A(l<$~1e|Tm&ErE~|!swxa_PcdG4{j$rS1X?FqIhm6rO#0=JWz;rNbeXNvJozLXm^&ap z3WNm{cB9m&V#YXVxEWe&Za6er@4jLl*Z)Ey1{F&?1CEaReWOzz(%3s$`R{kzPwlmI zyKDcXX=1bZUcFGS8(%%S{`txjO$iG;OHM8DC}O^ODen^M2{;|YFnc-^_>SJsw~OUC ze_68?Z=Rrhh7?KF#A-IGdb4P$LX6_?{Uq!WK}z*BwK(9&8mWZ4SU_ks2hNr*Ag#6D zWLoCePa$X`7z*qOCf;=mYIaa?-uZ~Q`RDXIRkbF^b*^D>yEq;aT@o5*Y_w8u7`z9Q zNO2AVL#!uerTCEZawIyvlH)-#Xyr4xZVQ@#h+lip$vqGhb{76!C_JdCU(-#Kuj^Au zPTxQNnj{T2-bxL+iAdv`FauIW60}1qW`A9++j!lIRW5LvG!jIrcN+OQ&*o;7RCgzN z9CW@k-%RvFo)JSE{!p&e*DWsB$1l_2u$6EmFxx^P!fx%o(pf`3H%fcU7)BOqQ{&7X z+}tTH`4Hm5Us8lkffM5Fd0Fz zjD8)#M~6g~Ri)pLd%tXLxeaorK!9%oJ8V7l0Ix&St~$PupiyJGBHJsCqkFfB7db2? zv=}!a@HYvXzg7D!YP?!;O`TpmL6W`aPWty05 ze-09VD@hIqL&4EYz=#n6ch%lD`I$a1=h6bH!AT)$lZ9xlVs z1W2@if{{~*pT$W0BYG970ebCxkEqg!d+V*KqcMvWl@d)_5rwOV#5ijr!Vm(A z2qQ49Yrw1Rtq-~^ZY0>mNU4etBxcbkN*O62Eh4>FKcvvkMQwl~HH!>Ca zhjRx-`Eb+v{%y=Pbu}>SN#d_s#dD5+fSPOsJ_nTJce#B3cK?<1L39h#Pbcdnj^l++ z)U%CTW22yhs5bs#7nVGY`{}nTD*nuHxoW4;H>)w%B#(ILWD`Fe`oxH)zF-tifa`x? zxl>iETO!~^wX#VoDi%3{y})5MRkfD~A~bRHAZm9VYQ|N&wFesw120K$II*01T9w|| zjyIK1dFMWo-W^&XcWtSu7oB- zGy89t30_3dU2ZlEr%56Alzt-wm#8})g$6~mM^dJ72NQHyy_H0UN1KH{`2Fgz7!l~H z=6$8%^&o<45(A7>Cd>%J+|k~3z7=L-@tU{&!I{1FeyeHe6_%2n>i6id`O-{b`fk-l zLx~^`6P``1Lzc0eIYt1B4H6AOZPxGRayZs|sei}A7#EXcJ*XxFg8Fd2OmrA~vsY~# zy>4=Yp$d$#$#q)#o}ioXhtl=MCeH!xymzyiNzI2&H#q61h$mU&gA~v>q-u^hRDFE~ z_OAx9cj4~wrCmls_he0I-Ydv)AshK3ZX|qLJWibO3s9u6r7r0SccXA04gb^tu!r9! z|3ikRPyaED9B26A$C?0c|z+{Mx`@=n#k7r?x9p2D)yCo$CTH}a#5Mf2G96mWx z$@kF|!Mq%sxfy}`;WCTeg}fIet}uF0fD4Kc@vSBrs8zxy^^3l%NO(BQq;1MdQk1#CUSOV6gOgeguXl&T zPRvI1jl~TMzKP#Av(R~uzT$NGk?s=o-jN}Ams{dUBFGn>%y836x1{Q-^?NgG>XQht=uPtLY`rggbNcfZ zkC;+NV<|GfIDCy9)om{^r0?)_dkVzqwr#*qsOU5o{$PDN7!#Dd^FjS^K_pqnfMzoZ z38+ccB;40a62Kzzbju@2B&8!)f9N)Gk^C}4%*A<=K-vEu69LKg8Bcis_cKR0rv`n- ztpLm~PIx-!*YZZ3r(xiv3ohyHRAb{8eCyPSoMQ+ib4kjW6#GQ=&0Go%1@Lyi(00rtPu zDiek|v7g?Y?O&Z#^bHMbcd;ObUWjH|7gc}U zt3yvt7p@Umq9ddw#-V7%2V>I(%QR_;&|9#{|Fya-_VDD`z0w4`!sbwY{r#M+BP9Lg z_fiL!pGQjgnZ7Z$BXfNvI!Ch()jZ?9RdupkLmCiv_nD`rnda(U<8g?2>}~`F57gL8 zhxCg}B&Hun5}6hsO%qhXHtgz*@UeUAs^8+IF3IByRy%;;1Bb zOH;X4g>72%Gdu1rE=jr6`uvH^%J44G8x5@ndAOY&iyaIphJ{o8>bP;_D+5l_%}v+Y6XpS|5q-yQzNkFaHG%qg4@Zc zi=)_74mRm4*lZSNr^whYwD}&z*E@>+UrAf23<0LcLN3V(`)8An57d11__bUu@;+1+ zX8*|hCLRCdI*M0O>Yg&%HWD!lU^bO)iu!~An`Qn$C7Tv(-NO=FLv1_AxjzjKp{ zSy?_0#-@=&;7zeYb8u_g@zclyTpps;)9hP(kQQS1K80%Y9dlbtB`;M|?yvoJoDkiv zw7qeWLzju3uyJ>J!jv{G@*g)NtrT?~ya?zQ#!E4lbMBwhZn#y{5k*Zxh@wwpXXNMl z7F~bGiuOvv1?37A&J_o|zJxM6_#duUA`Kyy>N)!2zt8qQV06h5W}sz!tyvL%nj$8X zjQpmS`G zUle~`^>g$TO}kE4*tmEdM7F0Z_I2*>ugf#>WELVVqgN4X>zUjWqn<1FcHX`tZW$RX zkZJZfhToj->va$dCcq`4H$kC70Ys^awQD#^>_RjA)(K}Is8sC&7Itd`$A0C$54HO) z)n5?idVy+%#k=^Iy5^-xA&mLEcs941IQ)2X`~(Ku%{0InuG6 zPue~%dC+~I=G1?mQwL`oSW3zX&^C?pn5Iiw567+m0Vkd1tc#gkc^DjV(D^%_8;3dm zme+MWJi#fb6kN>&Hf)#$pqu1(&p}qhSh4^;H|huX>K#J#%IDf$A_iS~QAy`+6wuHn zhEvJZ28 zc3VnRKh>FvM(^Lcfc2-Oobx>XDXs&i7T5IvV1*9jDJnS*wWs}CZ^8p$h5Pj4M@*)H zAqbaXsK|2#?imYlBpER~v3xh=oYh!OQkpy^d*zn;oMk1=mUCCfnld3FkU@ogo3K4^ zxr=JZ(w5Dl=O=O_0juQUVw|JGk0*Y@<#52=im2UH+bg1O+W0now-5*sh36fk9^dLgdoP@SrsR9Pcc8Zcf`%&W`{lwnNZ!P=+oy=o^ yr~7qm1;w!c52mmGHFw$n(?x@y7*J53pG0~vx3X-xcK=!PpkyQz#Op*2gZ~H9psOeV literal 0 HcmV?d00001 diff --git a/docs/_static/osi-badge-light.svg b/docs/_static/osi-badge-light.svg new file mode 100644 index 0000000..06969ce --- /dev/null +++ b/docs/_static/osi-badge-light.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/conf.py b/docs/conf.py index 7b3f7d2..5755bfc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -269,22 +269,43 @@ def setup(app: Sphinx) -> None: # Code blocks "color-code-foreground": "black", "color-code-background": "#f8f9fb", - } + }, + "footer_icons": [ + { + "name": "ISARICAnalytics@GitHub", + "url": "https://github.com/ISARICResearch/ISARICAnalytics", + "html": """ + + + + """, + "class": "", + }, + ], } + +# Override the default sidebar listing by commenting out the ethical ads sidebar. +html_sidebars = { + "**": [ + "sidebar/scroll-start.html", + "sidebar/brand.html", + "sidebar/search.html", + "sidebar/navigation.html", + # "sidebar/ethical-ads.html", + "sidebar/scroll-end.html", + ] +} + # Force pygments style in dark mode back to the light variant pygments_dark_style = "tango" -# html_logo = '_static/logo.png' +html_logo = '_static/isaric-logo.png' # Relative path (from the ``docs`` folder) to the static files folder - so # ``_static`` should be one level below ``docs``. html_static_path = ["_static"] -# Custom CSS file(s) - currently source the Font Awesome CSS classes to support -# Font Awesome icons. for more information see: -# -# https://sphinx-design.readthedocs.io/en/latest/badges_buttons.html#fontawesome-icons -# +# Custom CSS file(s) html_css_files = [ "css/custom.css", ] diff --git a/docs/index.rst b/docs/index.rst index 16f1b44..f51a96e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,6 +8,13 @@ The `ISARIC Analytics `_ lib - ISARIC data analytics - ISARIC data visualisation +ISARICAnalytics is licensed under the open source compliant `MIT license `_. + +.. image:: _static/osi-badge-light.svg + :target: https://opensource.org/license/mit + :height: 200px + :width: 200px + Installation ------------ From 8b6faf77764941d8f8da54eeba8b00e454a30fc7 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Wed, 13 May 2026 13:42:37 +0100 Subject: [PATCH 33/34] docs: tidy up conf --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5755bfc..8181390 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -278,7 +278,7 @@ def setup(app: Sphinx) -> None: - """, + """, # noqa : E501 "class": "", }, ], @@ -299,7 +299,7 @@ def setup(app: Sphinx) -> None: # Force pygments style in dark mode back to the light variant pygments_dark_style = "tango" -html_logo = '_static/isaric-logo.png' +html_logo = "_static/isaric-logo.png" # Relative path (from the ``docs`` folder) to the static files folder - so # ``_static`` should be one level below ``docs``. From 8c4ca0c10b8dca4d03ff5a9f57e4530ecbcf0483 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Wed, 13 May 2026 13:51:13 +0100 Subject: [PATCH 34/34] chore: update README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3e0151c..2724097 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,7 @@ characteristics that allow some automation during research analyses and the re-u elements of analysis pipelines to similar contexts. This package is designed to support Reusable Analytical Pipelines for Infectious Diseases (RAPIDs), which is based on the concept of [Reproducible Analytical Pipelines](https://analysisfunction.civilservice.gov.uk/support/reproducible-analytical-pipelines/). + +## Documentation + +Project documentation is available at https://isaricanalytics.readthedocs.io/en/latest. It is built with [Sphinx](https://www.sphinx-doc.org/en/) from content and configuration defined in the [`docs`](https://github.com/ISARICResearch/VERTEX/tree/main/docs) subfolder.