From 1a53432dcff95eb41106c329683767ee8770470d Mon Sep 17 00:00:00 2001 From: remydubois Date: Tue, 23 Dec 2025 16:01:29 +0100 Subject: [PATCH] first commit --- .editorconfig | 15 + .github/pull_request_template.md | 4 + .github/workflows/make-json.yml | 55 ++ .github/workflows/register-template-repos.yml | 32 + .gitignore | 7 + .pre-commit-config.yaml | 81 ++ LICENSE | 29 + README.md | 68 ++ ...se_affiliated_package_review_guidelines.md | 142 ++++ packages/CellAnnotator/meta.yaml | 19 + packages/CellCharter/meta.yaml | 22 + packages/CellMapper/meta.yaml | 18 + packages/CellOracle/meta.yaml | 45 ++ packages/CellRank/meta.yaml | 26 + packages/Cell_BLAST/meta.yaml | 20 + packages/CellphoneDB/meta.yaml | 34 + packages/Cirrocumulus/meta.yaml | 21 + packages/DRVI/meta.yaml | 26 + packages/DoubletDetection/meta.yaml | 21 + packages/GPTBioInsightor/meta.yaml | 19 + packages/GRnnData/meta.yaml | 22 + packages/LazySlide/meta.yaml | 19 + packages/Mowgli/meta.yaml | 21 + packages/Multivelo/meta.yaml | 20 + packages/PEAKQC/meta.yaml | 19 + packages/PILOT/meta.yaml | 36 + packages/ParTIpy/meta.yaml | 19 + packages/PathML/meta.yaml | 27 + packages/PyDESeq2/meta.yaml | 23 + packages/Rectangle/meta.yaml | 19 + packages/SC2Spa/meta.yaml | 23 + packages/SCALEX/meta.yaml | 20 + packages/STMiner/meta.yaml | 18 + packages/SnapATAC2/logo.svg | 40 + packages/SnapATAC2/meta.yaml | 24 + packages/TreeData/meta.yaml | 17 + packages/anndata-for-R/meta.yaml | 21 + packages/anndata/logo.svg | 1 + packages/anndata/meta.yaml | 24 + packages/anndataR/logo.svg | 108 +++ packages/anndataR/meta.yaml | 24 + packages/annsel/meta.yaml | 21 + packages/benGRN/meta.yaml | 21 + packages/bento-tools/meta.yaml | 19 + packages/biolord/meta.yaml | 19 + packages/cell2location/meta.yaml | 25 + packages/cellxgene/meta.yaml | 30 + packages/cookiecutter-scverse/meta.yaml | 14 + packages/dandelion/meta.yaml | 28 + packages/decoupler/logo.svg | 65 ++ packages/decoupler/meta.yaml | 24 + packages/delnx/meta.yaml | 21 + packages/dynamo-release/meta.yaml | 22 + packages/ecosystem-packages/meta.yaml | 13 + packages/epiScanpy/meta.yaml | 27 + packages/eschr/meta.yaml | 21 + packages/favapy/meta.yaml | 21 + packages/flowsom/meta.yaml | 28 + packages/governance/meta.yaml | 14 + packages/gssnng/meta.yaml | 24 + packages/hotspot/meta.yaml | 20 + packages/illico/meta.yaml | 19 + packages/infercnvpy/meta.yaml | 17 + packages/integration-testing/meta.yaml | 13 + packages/kompot/logo.png | Bin 0 -> 138271 bytes packages/kompot/meta.yaml | 34 + packages/liana/meta.yaml | 22 + packages/maxspin/meta.yaml | 19 + packages/moscot/meta.yaml | 24 + packages/mudata/logo.svg | 117 +++ packages/mudata/meta.yaml | 24 + packages/muon/logo.svg | 1 + packages/muon/meta.yaml | 23 + packages/novae/meta.yaml | 21 + packages/omicverse/meta.yaml | 24 + packages/palantir/meta.yaml | 33 + packages/panpipes/meta.yaml | 31 + packages/pcdl/meta.yaml | 30 + packages/pegasus/meta.yaml | 27 + packages/pertpy/logo.svg | 4 + packages/pertpy/meta.yaml | 25 + packages/popV/meta.yaml | 17 + packages/pyLemur/meta.yaml | 20 + packages/pySCENIC/meta.yaml | 32 + packages/pyUCell/meta.yaml | 26 + packages/pycea/meta.yaml | 17 + packages/pychromVAR/meta.yaml | 18 + packages/pytximport/meta.yaml | 21 + packages/rapids-singlecell/logo.svg | 75 ++ packages/rapids-singlecell/meta.yaml | 21 + packages/scCellFie/meta.yaml | 24 + packages/scDataLoader/meta.yaml | 25 + packages/scFates/meta.yaml | 27 + packages/scGen/meta.yaml | 27 + packages/scLiTr/meta.yaml | 20 + packages/scPRINT/meta.yaml | 27 + packages/scXpand/meta.yaml | 26 + packages/scanpro/meta.yaml | 20 + packages/scanpy/logo.svg | 1 + packages/scanpy/meta.yaml | 28 + packages/schist/meta.yaml | 20 + packages/scib/meta.yaml | 22 + packages/scirpy/logo.svg | 1 + packages/scirpy/meta.yaml | 25 + packages/scmcp/meta.yaml | 17 + packages/sctriangulate/meta.yaml | 18 + packages/scvelo/meta.yaml | 18 + packages/scverse-tutorials/meta.yaml | 15 + packages/scverse.github.io/meta.yaml | 12 + packages/scvi-tools/logo.svg | 1 + packages/scvi-tools/meta.yaml | 44 ++ packages/scxmatch/meta.yaml | 27 + packages/scyan/meta.yaml | 23 + packages/sift-sc/meta.yaml | 20 + packages/sincei/meta.yaml | 33 + packages/sobolev-alignment/meta.yaml | 23 + packages/sopa/meta.yaml | 23 + packages/spatial-eggplant/meta.yaml | 19 + packages/spatialdata/logo.svg | 108 +++ packages/spatialdata/meta.yaml | 23 + packages/spatialproteomics/meta.yaml | 23 + packages/spatiomic/meta.yaml | 21 + packages/squidpy/logo.svg | 80 ++ packages/squidpy/meta.yaml | 26 + packages/stats/meta.yaml | 13 + packages/symphonypy/meta.yaml | 18 + packages/tangram/meta.yaml | 23 + packages/vitessce/meta.yaml | 35 + packages/wsidata/meta.yaml | 18 + packages/zellkonverter/logo.svg | 358 +++++++++ packages/zellkonverter/meta.yaml | 21 + scripts/README.md | 6 + scripts/pyproject.toml | 80 ++ scripts/src/ecosystem_scripts/__init__.py | 0 scripts/src/ecosystem_scripts/_logging.py | 13 + scripts/src/ecosystem_scripts/schema.json | 261 +++++++ .../template_repo_registry.py | 140 ++++ .../ecosystem_scripts/validate_registry.py | 433 +++++++++++ scripts/uv.lock | 690 ++++++++++++++++++ template-repos.yml | 142 ++++ 140 files changed, 5599 insertions(+) create mode 100644 .editorconfig create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/make-json.yml create mode 100644 .github/workflows/register-template-repos.yml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 affiliated/scverse_affiliated_package_review_guidelines.md create mode 100644 packages/CellAnnotator/meta.yaml create mode 100644 packages/CellCharter/meta.yaml create mode 100644 packages/CellMapper/meta.yaml create mode 100644 packages/CellOracle/meta.yaml create mode 100644 packages/CellRank/meta.yaml create mode 100644 packages/Cell_BLAST/meta.yaml create mode 100644 packages/CellphoneDB/meta.yaml create mode 100644 packages/Cirrocumulus/meta.yaml create mode 100644 packages/DRVI/meta.yaml create mode 100644 packages/DoubletDetection/meta.yaml create mode 100644 packages/GPTBioInsightor/meta.yaml create mode 100644 packages/GRnnData/meta.yaml create mode 100644 packages/LazySlide/meta.yaml create mode 100644 packages/Mowgli/meta.yaml create mode 100644 packages/Multivelo/meta.yaml create mode 100644 packages/PEAKQC/meta.yaml create mode 100644 packages/PILOT/meta.yaml create mode 100644 packages/ParTIpy/meta.yaml create mode 100644 packages/PathML/meta.yaml create mode 100644 packages/PyDESeq2/meta.yaml create mode 100644 packages/Rectangle/meta.yaml create mode 100644 packages/SC2Spa/meta.yaml create mode 100644 packages/SCALEX/meta.yaml create mode 100644 packages/STMiner/meta.yaml create mode 100644 packages/SnapATAC2/logo.svg create mode 100644 packages/SnapATAC2/meta.yaml create mode 100644 packages/TreeData/meta.yaml create mode 100644 packages/anndata-for-R/meta.yaml create mode 100644 packages/anndata/logo.svg create mode 100644 packages/anndata/meta.yaml create mode 100644 packages/anndataR/logo.svg create mode 100644 packages/anndataR/meta.yaml create mode 100644 packages/annsel/meta.yaml create mode 100644 packages/benGRN/meta.yaml create mode 100644 packages/bento-tools/meta.yaml create mode 100644 packages/biolord/meta.yaml create mode 100644 packages/cell2location/meta.yaml create mode 100644 packages/cellxgene/meta.yaml create mode 100644 packages/cookiecutter-scverse/meta.yaml create mode 100644 packages/dandelion/meta.yaml create mode 100644 packages/decoupler/logo.svg create mode 100644 packages/decoupler/meta.yaml create mode 100644 packages/delnx/meta.yaml create mode 100644 packages/dynamo-release/meta.yaml create mode 100644 packages/ecosystem-packages/meta.yaml create mode 100644 packages/epiScanpy/meta.yaml create mode 100644 packages/eschr/meta.yaml create mode 100644 packages/favapy/meta.yaml create mode 100644 packages/flowsom/meta.yaml create mode 100644 packages/governance/meta.yaml create mode 100644 packages/gssnng/meta.yaml create mode 100644 packages/hotspot/meta.yaml create mode 100644 packages/illico/meta.yaml create mode 100644 packages/infercnvpy/meta.yaml create mode 100644 packages/integration-testing/meta.yaml create mode 100644 packages/kompot/logo.png create mode 100644 packages/kompot/meta.yaml create mode 100644 packages/liana/meta.yaml create mode 100644 packages/maxspin/meta.yaml create mode 100644 packages/moscot/meta.yaml create mode 100644 packages/mudata/logo.svg create mode 100644 packages/mudata/meta.yaml create mode 100644 packages/muon/logo.svg create mode 100644 packages/muon/meta.yaml create mode 100644 packages/novae/meta.yaml create mode 100644 packages/omicverse/meta.yaml create mode 100644 packages/palantir/meta.yaml create mode 100644 packages/panpipes/meta.yaml create mode 100644 packages/pcdl/meta.yaml create mode 100644 packages/pegasus/meta.yaml create mode 100644 packages/pertpy/logo.svg create mode 100644 packages/pertpy/meta.yaml create mode 100644 packages/popV/meta.yaml create mode 100644 packages/pyLemur/meta.yaml create mode 100644 packages/pySCENIC/meta.yaml create mode 100644 packages/pyUCell/meta.yaml create mode 100644 packages/pycea/meta.yaml create mode 100644 packages/pychromVAR/meta.yaml create mode 100644 packages/pytximport/meta.yaml create mode 100644 packages/rapids-singlecell/logo.svg create mode 100644 packages/rapids-singlecell/meta.yaml create mode 100644 packages/scCellFie/meta.yaml create mode 100644 packages/scDataLoader/meta.yaml create mode 100644 packages/scFates/meta.yaml create mode 100644 packages/scGen/meta.yaml create mode 100644 packages/scLiTr/meta.yaml create mode 100644 packages/scPRINT/meta.yaml create mode 100644 packages/scXpand/meta.yaml create mode 100644 packages/scanpro/meta.yaml create mode 100644 packages/scanpy/logo.svg create mode 100644 packages/scanpy/meta.yaml create mode 100644 packages/schist/meta.yaml create mode 100644 packages/scib/meta.yaml create mode 100644 packages/scirpy/logo.svg create mode 100644 packages/scirpy/meta.yaml create mode 100644 packages/scmcp/meta.yaml create mode 100644 packages/sctriangulate/meta.yaml create mode 100644 packages/scvelo/meta.yaml create mode 100644 packages/scverse-tutorials/meta.yaml create mode 100644 packages/scverse.github.io/meta.yaml create mode 100755 packages/scvi-tools/logo.svg create mode 100644 packages/scvi-tools/meta.yaml create mode 100644 packages/scxmatch/meta.yaml create mode 100644 packages/scyan/meta.yaml create mode 100644 packages/sift-sc/meta.yaml create mode 100644 packages/sincei/meta.yaml create mode 100644 packages/sobolev-alignment/meta.yaml create mode 100644 packages/sopa/meta.yaml create mode 100644 packages/spatial-eggplant/meta.yaml create mode 100644 packages/spatialdata/logo.svg create mode 100644 packages/spatialdata/meta.yaml create mode 100644 packages/spatialproteomics/meta.yaml create mode 100644 packages/spatiomic/meta.yaml create mode 100644 packages/squidpy/logo.svg create mode 100644 packages/squidpy/meta.yaml create mode 100644 packages/stats/meta.yaml create mode 100644 packages/symphonypy/meta.yaml create mode 100644 packages/tangram/meta.yaml create mode 100644 packages/vitessce/meta.yaml create mode 100644 packages/wsidata/meta.yaml create mode 100644 packages/zellkonverter/logo.svg create mode 100644 packages/zellkonverter/meta.yaml create mode 100644 scripts/README.md create mode 100644 scripts/pyproject.toml create mode 100644 scripts/src/ecosystem_scripts/__init__.py create mode 100644 scripts/src/ecosystem_scripts/_logging.py create mode 100644 scripts/src/ecosystem_scripts/schema.json create mode 100644 scripts/src/ecosystem_scripts/template_repo_registry.py create mode 100644 scripts/src/ecosystem_scripts/validate_registry.py create mode 100644 scripts/uv.lock create mode 100644 template-repos.yml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..4d1d5b38 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yml,yaml}] +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..28447e72 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,4 @@ + diff --git a/.github/workflows/make-json.yml b/.github/workflows/make-json.yml new file mode 100644 index 00000000..389c6816 --- /dev/null +++ b/.github/workflows/make-json.yml @@ -0,0 +1,55 @@ +name: Make JSON +on: + pull_request: + branches: [main] + push: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + mkjson: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: astral-sh/setup-uv@v7 + - name: Execute validation script and create output directory + run: | + uvx --from ./scripts validate-registry --registry-dir packages --outdir=build + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + FORCE_COLOR: "1" + COLUMNS: "150" + - name: Upload GitHub Pages artifact + uses: actions/upload-pages-artifact@v4 + with: + path: "build" + + deploy: + runs-on: ubuntu-latest + needs: mkjson + + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment + permissions: + pages: write # to deploy to Pages + id-token: write + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + if: github.ref == 'refs/heads/main' + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + - name: Trigger website build + run: | + curl -XPOST \ + -u "scverse-bot:${{ secrets.BOT_GH_TOKEN }}" \ + -H "Accept: application/vnd.github.everest-preview+json" \ + -H "Content-Type: application/json" \ + https://api.github.com/repos/scverse/scverse.github.io/actions/workflows/gh-pages.yml/dispatches \ + --data '{"ref": "main"}' diff --git a/.github/workflows/register-template-repos.yml b/.github/workflows/register-template-repos.yml new file mode 100644 index 00000000..eb8cc40e --- /dev/null +++ b/.github/workflows/register-template-repos.yml @@ -0,0 +1,32 @@ +name: Register template repos + +on: + schedule: + # Twice a month: https://crontab.guru/#0_5_1,15_*_* + - cron: "0 5 1,15 * *" + workflow_dispatch: + +jobs: + register-template-repos: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + token: ${{ secrets.BOT_GH_TOKEN }} + - name: Install uv + uses: astral-sh/setup-uv@v7 + - name: Update template repo registry + run: uvx --from ./scripts register-template-repos template-repos.yml + env: + GITHUB_TOKEN: "${{ secrets.BOT_GH_TOKEN }}" + FORCE_COLOR: "1" + COLUMNS: "150" + - uses: EndBug/add-and-commit@v9 + with: + add: ./template-repos.yml + author_name: scverse-bot + author_email: core-team@scverse.org + message: "Updated template-repos.yml" + push: true + - name: Show diff + run: git diff HEAD~1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..7f101b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.DS_STORE +__pycache__/ +.*cache/ + +/.vscode/ +.venv +schema.pyi diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..45443f8f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,81 @@ +fail_fast: false +default_language_version: + python: python3 +default_stages: + - pre-commit + - pre-push +minimum_pre_commit_version: 2.16.0 +repos: + # all files + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: detect-private-key + - id: check-ast + - id: end-of-file-fixer + - id: mixed-line-ending + args: [--fix=lf] + - id: trailing-whitespace + - id: check-case-conflict + - repo: https://github.com/rbubley/mirrors-prettier + rev: v3.7.4 + hooks: + - id: prettier + # package metadata + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.36.0 + hooks: + - id: check-jsonschema + files: "scripts/src/ecosystem_scripts/schema.json" + args: ["--check-metaschema"] + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.36.0 + hooks: + - id: check-jsonschema + files: "packages/.*/meta.yaml" + args: ["--schemafile", "scripts/src/ecosystem_scripts/schema.json"] + - repo: local + hooks: + - id: forbid-to-commit + name: Check files in `packages` directory + entry: | + Only `meta.yaml` and logo files are permitted in the packages directory + language: fail + files: "^packages/.*$" + exclude: "^packages/.*/(meta.yaml|logo\\..*)$" + # scripts + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.10 + hooks: + - id: ruff-check + args: [--fix, --exit-non-zero-on-fix] + files: ^scripts/.*$ + - id: ruff-format + files: ^scripts/.*$ + - repo: https://github.com/tox-dev/pyproject-fmt + rev: v2.11.1 + hooks: + - id: pyproject-fmt + - repo: https://github.com/camptocamp/jsonschema-gentypes + rev: "2.13.0" + hooks: + - id: jsonschema-gentypes + args: + - --json-schema=scripts/src/ecosystem_scripts/schema.json + - --python=scripts/src/ecosystem_scripts/schema.pyi + files: ^scripts/.*/schema.json$ + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.19.1 + hooks: + - id: mypy + args: [--config-file=scripts/pyproject.toml, scripts] + pass_filenames: false + additional_dependencies: + - httpx + - httpx-retries + - types-jsonschema + - pillow + - pygithub + - types-PyYAML + - rich + files: ^scripts/.*$ diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..efbf3e28 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2022, scverse +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..e12766ba --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ +# Scverse Ecosystem Packages + +This repository contains the list of scverse ecosystem packages that are displayed on scverse.org and are part of +the scverse® project. +The goal is to increase visibility of ecosystem packages and make it easier for users to find appropriate software. +Registered ecosystem packages can also get their own tag to use on the [scverse forum](https://discourse.scverse.org) for user discussion. +Authors of these packages can be added to the [scverse github organization](https://github.com/scverse). +In the future, we may also test releases of core packages against the test suites of ecosystem packages. + +If a package is part of this list, it means it fulfills certain minimum requirements as outlined below. +It **does not** imply endorsement or that an in-depth review has been performed. + +**Hint:** If you want to receive notifications about new ecosystem packages, simply use GitHub's "watch" functionality for this repository. + +## How can my package become part of the list? + +Submit a pull-request adding a `meta.yaml` file for your package to the `packages` directory. + +- Please copy the checklist from below into the pull request description and answer all questions. +- Please refer to other entries for examples +- The full definition of available fields is available in [`schema.json`](scripts/src/ecosystem_scripts/schema.json) +- You can add a logo in svg/png/webp format if you like. Currently it is not used on our website, though. + +## What are the requirements for an ecosystem package? + +For a package to become an approved ecosystem package, it must fulfill all mandatory requirements from the checklist below. + +Ecosystem packages can be written in non-Python languages as long as they fulfill the above requirements. + +If you cannot or do not want to comply with these requirements, you are still free to make your package interoperable with scverse by using our datastructures, but we will not list your package on our ecosystem page. + +## Checklist for adding packages + +### Mandatory + +Name of the tool: XXX + +Short description: XXX + +How does the package use scverse data structures (please describe in a few sentences): XXX + +- [ ] The code is publicly available under an [OSI-approved](https://opensource.org/licenses/alphabetical) license +- [ ] The package provides versioned releases +- [ ] The package can be installed from a standard registry (e.g. PyPI, conda-forge, bioconda) +- [ ] Automated tests cover essential functions of the package and a reasonable range of inputs and conditions [^1] +- [ ] Continuous integration (CI) automatically executes these tests on each push or pull request [^2] +- [ ] The package provides API documentation via a website or README[^3] +- [ ] The package uses scverse datastructures where appropriate (i.e. AnnData, MuData or SpatialData and their modality-specific extensions) +- [ ] I am an author or maintainer of the tool and agree on listing the package on the scverse website + +### Recommended + +- [ ] Please announce this package on scverse communication channels (zulip, discourse, twitter) +- [ ] Please tag the author(s) these announcements. Handles (e.g. `@scverse_team`) to include are: + - Zulip: + - Discourse: + - Mastodon: + - Bluesky: + - Twitter: + +- [ ] The package provides tutorials (or "vignettes") that help getting users started quickly +- [ ] The package uses the [scverse cookiecutter template](https://github.com/scverse/cookiecutter-scverse). + +[^1]: We recommend thtat tests cover at least all user facing (public) functions. Minimal tests ensure that the function does not fail on an example data set. Ideally, tests also ensure the correctness of the results, e.g. by comparing against a snapshot. + +[^2]: Continuous integration means that software tests are automatically executed on every push to the git repository. This guarantees they are always run and that they are run in a clean environment. Scverse ecosystem packages most commonly use [GitHub Actions](https://github.com/features/actions) for CI. For an example, check out our [cookiecutter template](https://github.com/scverse/cookiecutter-scverse). + +[^3]: By API documentation, we mean an overview of _all_ public functions provided a package, with documentation of their parameters. For an example, see the [Scanpy documentation](https://scanpy.readthedocs.io/en/stable/api/preprocessing.html). In simple cases, this can be done manually in a README file. For anything more complex, we recommend the [Sphinx Autodoc plugin](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html) diff --git a/affiliated/scverse_affiliated_package_review_guidelines.md b/affiliated/scverse_affiliated_package_review_guidelines.md new file mode 100644 index 00000000..0afaa4f0 --- /dev/null +++ b/affiliated/scverse_affiliated_package_review_guidelines.md @@ -0,0 +1,142 @@ +# **Reviewing scverse-affiliated packages** + +This document outlines the criteria for reviewing packages applying to become scverse-affiliated and is intended for reviewers. + +Thank you for participating in the review process for scverse-affiliated package submissions. Your insights and evaluations play a crucial role in maintaining the quality and integrity of the scverse ecosystem. + +Unlike a typical academic paper review, your report will be combined with a coordinator's review and may not be directly shared with the authors. Please submit your review report privately to the coordinator who contacted you. + +The review focuses on several key areas as detailed below. You are expected to base your review on these criteria, but you are also welcome to highlight any other relevant aspects. For each category, please provide a 'traffic light' rating and include comments, especially where there is room for improvement. + +### **Traffic Light Rating System** + + +
RedIndicates major issues or shortcomings. Affiliated packages must resolve any red scores to be accepted or remain listed. +
OrangeAcceptable but with notable deficiencies. This serves as both a caution to users and a motivator for developers to improve. +
GreenRepresents the ideal standard. All-green packages may be featured prominently within the scverse ecosystem. +
+ +The review categories are as follows, with specific keywords in **`monospaced text`** for use in the scverse registry: + +### **Functionality (`'functionality'`)** + +Assess whether the package's scope is relevant and useful within the scverse ecosystem. + +### **Integration with scverse (`'ecointegration'`)** + +Evaluate the package's use of scverse and other related libraries, checking for unnecessary duplication or missed opportunities for integration. + +### **License (`'license'`)** + +Verify that the the code is publicly available under an OSI-approved licensei + +### **Distribution (`'distribution'`)** + +Verify that the package can be installed from a standard registry (e.g. PyPI, conda-forge, bioconda) + +### **Documentation (`'documentation'`)** + +Review the package's documentation for completeness, clarity, and usefulness to potential users. + +### **Testing (`'testing'`)** + +Consider the coverage and effectiveness of the package's automated tests. + +### **Development status (`'devstatus'`)** + +Determine the package's current development stage and the versioned releases. + +### **Python 3 compatibility (`'python3'`)** + +Verify that the package is compatible with Python 3. + +--- + +**Detailed Guidelines for Each Category:** + +### **Functionality ('functionality')** + +Evaluate the scope of the package: + + +
RedNot relevant to the scverse community. +
GreenBroadly useful across the scverse community. +
+ +### **Integration with scverse ('ecointegration')** + +Assess integration with scverse: + + +
RedLittle to no use of scverse structures where applicable. +
GreenThe package uses scverse datastructures where appropriate (i.e. AnnData, MuData or SpatialData and their modality-specific extensions). +
+ +### **License ('license')** + +Verify OSI-approved license: + + +
RedCode is not OSI-approved licensed. +
GreenCode is OSI-approved licensed. +
+ +### **Distribution ('distribution')** + +Evaluate the package's documentation: + + +
RedThe package cannot be installed from a standard registry. +
GreenThe package can be installed from a standard registry (e.g. PyPI, conda-forge, bioconda). +
+ +### **Documentation ('documentation')** + +Evaluate the package's documentation: + + +
RedInadequate or significantly lacking. +
GreenThe package provides API documentation via a website or README. +
+ +### **Testing ('testing')** + +Assess the package's testing practices: + + +
RedInsufficient test coverage or poorly implemented tests. +
GreenThe package uses automated software tests and runs them via continuous integration (CI). +
+ +### **Development status ('devstatus')** + +Determine the package's development status: + + +
RedThe package does not provide versioned releases. +
GreenThe package provides versioned releases. +
+ + +
RedSubmission by an individual who is neither an author nor a maintainer of the tool or/and does not agree on listing the package on the scverse website. +
GreenSubmission by an author or maintainer of the tool who agrees on listing the package on the scverse website. +
+ +### **Python 3 compatibility ('python3')** + +Check Python 3 compatibility: + + +
RedNot compatible with Python 3. +
GreenFully compatible with Python 3. +
+ +### **Recommended (`'recommended'`)** + + +
OrangeThe package does not provide tutorials (or "vignettes") that help getting users started quickly +
+ + +
OrangeThe package does not use the scverse cookiecutter template. +
diff --git a/packages/CellAnnotator/meta.yaml b/packages/CellAnnotator/meta.yaml new file mode 100644 index 00000000..bc84d0f2 --- /dev/null +++ b/packages/CellAnnotator/meta.yaml @@ -0,0 +1,19 @@ +name: CellAnnotator +description: | + CellAnnotator is a lightweight tool to query large language models for cell type labels in scRNA-seq data. It can incorporate prior knowledge, and it creates consistent labels across samples in your study. +project_home: https://github.com/quadbio/cell-annotator +documentation_home: https://cell-annotator.readthedocs.io/en/latest/ +install: + pypi: cell-annotator +tags: + - cell type labels + - openai + - large language models + - automatic annotation + - cell state +license: MIT +version: v0.1.3 +contact: + - Marius1311 +test_command: pip install -e '.[test]' && pytest +category: ecosystem diff --git a/packages/CellCharter/meta.yaml b/packages/CellCharter/meta.yaml new file mode 100644 index 00000000..f77a73bc --- /dev/null +++ b/packages/CellCharter/meta.yaml @@ -0,0 +1,22 @@ +name: CellCharter +description: | + CellCharter is a framework to identify, characterize and compare spatial domains from spatial omics and multi-omics data. +project_home: https://github.com/CSOgroup/cellcharter +documentation_home: https://cellcharter.readthedocs.io/ +tutorials_home: https://cellcharter.readthedocs.io/ +publications: + - 10.1038/s41588-023-01588-4 +install: + pypi: cellcharter +tags: + - spatial omics + - spatial clustering + - spatial domains + - gaussian mixture model +license: BSD-3-Clause +version: v0.3.1 +contact: + - marcovarrone +test_command: | + pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/CellMapper/meta.yaml b/packages/CellMapper/meta.yaml new file mode 100644 index 00000000..32f903cb --- /dev/null +++ b/packages/CellMapper/meta.yaml @@ -0,0 +1,18 @@ +name: CellMapper +description: | + CellMapper is a leightweight tool to transfer labels, expression values and embeddings from reference to query datasets using k-NN mapping. It's fast and versatile, applicable to mapping scenarios in space, across modalities, or from an atlas to a new query dataset. +project_home: https://github.com/quadbio/cellmapper +documentation_home: https://cellmapper.readthedocs.io/en/latest/ +install: + pypi: cellmapper +tags: + - k-NN based mapping + - rapids + - faiss + - query-to-reference +license: MIT +version: v0.1.2 +contact: + - Marius1311 +test_command: pip install -e '.[test]' && pytest +category: ecosystem diff --git a/packages/CellOracle/meta.yaml b/packages/CellOracle/meta.yaml new file mode 100644 index 00000000..503f0277 --- /dev/null +++ b/packages/CellOracle/meta.yaml @@ -0,0 +1,45 @@ +name: CellOracle +description: | + A computational tool that integrates single-cell transcriptome and epigenome profiles + to infer gene regulatory networks (GRNs), critical regulators of cell identity. +project_home: https://github.com/morris-lab/CellOracle +documentation_home: https://morris-lab.github.io/CellOracle.documentation/ +tutorials_home: https://morris-lab.github.io/CellOracle.documentation/ +publications: + - 10.1101/2020.02.17.947416 +install: + pypi: celloracle +tags: + - GRN + - TF +license: Apache-2.0 +version: v0.10.12 +contact: + - KenjiKamimoto-ac + - sam-morris + - cmhct7 +test_command: | + sudo apt-get update + sudo apt-get install -y bedtools + wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh + bash miniconda.sh -b -p $HOME/miniconda + source "$HOME/miniconda/etc/profile.d/conda.sh" + hash -r + conda config --set always_yes yes --set changeps1 no + #conda update -q conda + # Useful for debugging any issues with conda + conda info -a + # Create env + conda create -q -n test-environment python=3.8 + # command to install dependencies + conda activate test-environment + conda install cython numpy pytest + + # Check pip + echo pip_path + which pip + + pip install . + # command to run tests + pytest -v +category: ecosystem diff --git a/packages/CellRank/meta.yaml b/packages/CellRank/meta.yaml new file mode 100644 index 00000000..fa85b61a --- /dev/null +++ b/packages/CellRank/meta.yaml @@ -0,0 +1,26 @@ +name: CellRank +description: | + CellRank is a toolkit to uncover cellular dynamics based on Markov state modeling of single-cell data. + It contains two main modules - kernels compute cell-cell transition probabilities and estimators generate + hypothesis based on these. +project_home: https://github.com/theislab/cellrank +documentation_home: https://cellrank.readthedocs.io/en/stable/ +tutorials_home: https://cellrank.readthedocs.io/en/stable/ +publications: + - 10.1038/s41592-021-01346-6 +install: + pypi: cellrank +tags: + - ML + - cell-fate + - rna-velocity + - trajectory-generation +license: BSD-3-Clause +version: v1.5.1 +contact: + - Marius1311 + - michalk8 + - WeilerP +test_command: | + pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/Cell_BLAST/meta.yaml b/packages/Cell_BLAST/meta.yaml new file mode 100644 index 00000000..f0acb615 --- /dev/null +++ b/packages/Cell_BLAST/meta.yaml @@ -0,0 +1,20 @@ +name: Cell_BLAST +description: | + Cell BLAST is a cell querying tool for single-cell transcriptomics data. +project_home: https://github.com/gao-lab/Cell_BLAST +documentation_home: https://cblast.readthedocs.io/en/latest/ +publications: + - 10.1038/s41467-020-17281-7 +install: + pypi: Cell-BLAST +tags: + - BLAST +license: MIT +version: v0.3.8 +contact: + - Jeff1995 +test_command: | + pip install --upgrade pip flit + flit install -s + cd test && python test.py +category: ecosystem diff --git a/packages/CellphoneDB/meta.yaml b/packages/CellphoneDB/meta.yaml new file mode 100644 index 00000000..dc3f69ec --- /dev/null +++ b/packages/CellphoneDB/meta.yaml @@ -0,0 +1,34 @@ +name: CellphoneDB +description: | + CellphoneDB is a publicly available repository of HUMAN curated receptors, ligands and their interactions paired with a tool to interrogate your own single-cell transcriptomics data (or even bulk transcriptomics data if your samples represent pure populations!). A distinctive feature of CellphoneDB is that the subunit architecture of either ligands and receptors is taken into account, representing heteromeric complexes accurately. This is crucial, as cell communication relies on multi-subunit protein complexes that go beyond the binary representation used in most databases and studies. CellphoneDB also incorporates biosynthetic pathways in which we use the last representative enzyme as a proxy of ligand abundance, by doing so, we include interactions involving non-peptidic molecules. CellphoneDB includes only manually curated and reviewed molecular interactions with evidenced role in cellular communication. +project_home: https://github.com/ventolab/CellphoneDB +documentation_home: https://cellphonedb.readthedocs.io/en/latest/ +tutorials_home: https://github.com/ventolab/CellphoneDB/tree/master/notebooks +publications: + - 10.1038/s41586-018-0698-6 + - 10.1038/s41596-020-0292-x + - 10.1038/s41588-021-00972-2 + - 10.1038/s41586-022-04918-4 +install: + pypi: cellphonedb +tags: + - scRNA-seq + - cell-cell communication + - ligand-receptor + - single-cell + - python + - jupyter +license: MIT +version: v5.0.0 +contact: + - chapuzzo + - datasome + - ktroule + - luzgaral + - mvento + - prete + - rvento + - zktuong +test_command: | + git clone git@github.com:ventolab/CellphoneDB.git && pip install cellphonedb && pip install pytest && cd CellphoneDB/cellphonedb/src/tests/ && python3 -m pytest method_tests.py +category: ecosystem diff --git a/packages/Cirrocumulus/meta.yaml b/packages/Cirrocumulus/meta.yaml new file mode 100644 index 00000000..8a0ba053 --- /dev/null +++ b/packages/Cirrocumulus/meta.yaml @@ -0,0 +1,21 @@ +name: Cirrocumulus +description: | + Cirrocumulus is an interactive visualization tool for large-scale single-cell genomics data. +project_home: https://github.com/lilab-bcb/cirrocumulus +documentation_home: https://cirrocumulus.readthedocs.io/en/latest/ +tutorials_home: https://cirrocumulus.readthedocs.io/en/latest/ +publications: + - 10.1038/s41592-020-0905-x +install: + pypi: cirrocumulus +tags: + - visualization +license: BSD-3-Clause +version: v1.1.41 +contact: + - joshua-gould + - yihming + - gouwens +test_command: | + SETUPTOOLS_SCM_PRETEND_VERSION=0.0.1 pip install .[test,parquet] && pytest +category: ecosystem diff --git a/packages/DRVI/meta.yaml b/packages/DRVI/meta.yaml new file mode 100644 index 00000000..d86cad5f --- /dev/null +++ b/packages/DRVI/meta.yaml @@ -0,0 +1,26 @@ +name: DRVI +description: | + DRVI is a tool for the unsupervised disentanglement and integration of single-cell omics. + By providing interpretable latent dimensions, it allows users to identify cellular + heterogeneity and biological processes beyond traditional cell types, identify rare cell types, + and highlight developmental stages. DRVI is implemented using scvi-tools and includes a + set of utility functions for interacting with latent dimensions. +project_home: https://github.com/theislab/DRVI +documentation_home: https://drvi.readthedocs.io/latest/ +tutorials_home: https://drvi.readthedocs.io/latest/tutorials/index.html +publications: + - 10.1101/2024.11.06.622266 +install: + pypi: drvi-py +tags: + - disentanglement + - interpretability + - data integration + - variational inference + - deep learning +license: BSD-3-Clause +version: 0.2.0 +contact: + - moinfar +test_command: uvx hatch run pytest +category: ecosystem diff --git a/packages/DoubletDetection/meta.yaml b/packages/DoubletDetection/meta.yaml new file mode 100644 index 00000000..38fbf16f --- /dev/null +++ b/packages/DoubletDetection/meta.yaml @@ -0,0 +1,21 @@ +name: DoubletDetection +description: | + DoubletDetection is a Python3 package to detect doublets (technical errors) in single-cell + RNA-seq count matrices. +project_home: https://github.com/JonathanShor/DoubletDetection +documentation_home: https://doubletdetection.readthedocs.io/en/stable/ +tutorials_home: https://doubletdetection.readthedocs.io/en/stable/ +publications: + - 10.1016/j.cels.2019.03.003 +install: + pypi: doubletdetection +tags: + - doublet +license: MIT +version: v4.2 +contact: + - adamgayoso + - JonathanShor + - ambrosejcarr +test_command: pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/GPTBioInsightor/meta.yaml b/packages/GPTBioInsightor/meta.yaml new file mode 100644 index 00000000..8bd6f75e --- /dev/null +++ b/packages/GPTBioInsightor/meta.yaml @@ -0,0 +1,19 @@ +name: GPTBioInsightor +description: | + GPTBioInsightor is a tool designed for single-cell data analysis, particularly beneficial for newcomers to a biological field or those in interdisciplinary areas who may lack sufficient biological background knowledge. + GPTBioInsightor utilizes the powerful capabilities of large language models to help people quickly gain knowledge and insight, enhancing their work efficiency. +project_home: https://github.com/huang-sh/GPTBioInsightor +documentation_home: https://gptbioinsightor.readthedocs.io/ +install: + pypi: gptbioinsightor +tags: + - single-cell + - bioinformatics + - LLM + - AI +license: BSD-3-Clause +version: v0.3.0 +contact: + - huangsh +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/GRnnData/meta.yaml b/packages/GRnnData/meta.yaml new file mode 100644 index 00000000..3ed6f843 --- /dev/null +++ b/packages/GRnnData/meta.yaml @@ -0,0 +1,22 @@ +name: GRnnData +description: | + An onverload of anndata to more easily work with gene networks. + Allows easy conversion between anndata and grnndata and provide loads of usefull utilities functions. +project_home: https://github.com/cantinilab/GRnnData +documentation_home: https://cantinilab.github.io/GRnnData/ +publications: + - 10.1101/2024.07.29.605556 +install: + pypi: grnndata +tags: + - single cell + - RNAseq + - gene networks + - format + - utilities +license: MIT +version: v1.1.4 +contact: + - jkobject +test_command: pip install . && make test +category: ecosystem diff --git a/packages/LazySlide/meta.yaml b/packages/LazySlide/meta.yaml new file mode 100644 index 00000000..52f4a4fc --- /dev/null +++ b/packages/LazySlide/meta.yaml @@ -0,0 +1,19 @@ +name: LazySlide +description: | + LazySlide is a Python library for processing whole slide images (WSI) analysis. It provides a simple interface to perform robust preprocessing and advanced analysis for WSI. +project_home: https://github.com/rendeirolab/lazyslide +documentation_home: https://lazyslide.readthedocs.io/en/latest/ +install: + pypi: lazyslide +tags: + - Pathology + - Whole Slide Imaging + - PyTorch +license: MIT +version: v0.3.0 +contact: + - Mr-Milk + - eabila + - afrendeiro +test_command: uv run task test +category: ecosystem diff --git a/packages/Mowgli/meta.yaml b/packages/Mowgli/meta.yaml new file mode 100644 index 00000000..02e96f77 --- /dev/null +++ b/packages/Mowgli/meta.yaml @@ -0,0 +1,21 @@ +name: Mowgli +description: | + Paired single-cell multi-omics data integration with Optimal Transport-flavored Nonnegative Matrix Factorization +project_home: https://github.com/cantinilab/mowgli +documentation_home: https://mowgli.readthedocs.io +publications: + - 10.1101/2023.02.02.526825 +install: + pypi: mowgli +tags: + - single cell + - optimal transport + - multi omics + - data integration + - NMF +license: GPL-3.0-only +version: v0.2.0 +contact: + - gjhuizing +test_command: pip install . && pytest +category: ecosystem diff --git a/packages/Multivelo/meta.yaml b/packages/Multivelo/meta.yaml new file mode 100644 index 00000000..29abbdde --- /dev/null +++ b/packages/Multivelo/meta.yaml @@ -0,0 +1,20 @@ +name: Multivelo +description: | + A mechanistic model of gene expression that extends the popular RNA velocity + framework by incorporating epigenomic data. +project_home: https://github.com/welch-lab/MultiVelo +documentation_home: https://multivelo.readthedocs.io/en/latest/api.html +tutorials_home: https://multivelo.readthedocs.io/en/latest/MultiVelo_Demo.html +publications: + - 10.1038/s41587-022-01476-y +install: + pypi: multivelo +tags: + - rna velocity +license: BSD-3-Clause +version: 0.1.3 +contact: + - jw156605 + - danielee0707 + - jacobrepucci +category: ecosystem diff --git a/packages/PEAKQC/meta.yaml b/packages/PEAKQC/meta.yaml new file mode 100644 index 00000000..7b4350a2 --- /dev/null +++ b/packages/PEAKQC/meta.yaml @@ -0,0 +1,19 @@ +name: PEAKQC +description: periodicity evaluation in scATAC-seq data for quality assessment +project_home: https://github.com/loosolab/PEAKQC +documentation_home: https://loosolab.pages.gwdg.de/software/peakqc/ +publications: + - 10.1101/2025.02.20.639146 +install: + pypi: peakqc +tags: + - single cell + - ATAC-seq + - quality control +license: MIT +version: 0.1.3 +contact: + - jan1034 + - mlooso +test_command: pip install . && pytest +category: ecosystem diff --git a/packages/PILOT/meta.yaml b/packages/PILOT/meta.yaml new file mode 100644 index 00000000..55a7a222 --- /dev/null +++ b/packages/PILOT/meta.yaml @@ -0,0 +1,36 @@ +name: PILOT +description: | + PILOT is a Python library for Detection of PatIent-Level distances from single cell genomics and pathomics data with Optimal Transport. +project_home: https://github.com/CostaLab/PILOT +documentation_home: https://pilot.readthedocs.io/en/latest/api.html +tutorials_home: https://pilot.readthedocs.io/en/latest/ +publications: + - 10.1038/s44320-023-00003-8 +install: + conda_instructions: | + # Create a new conda environment with the required Python version and R base + conda create --name PILOT python=3.11.5 r-base + # Activate the new environment + conda activate PILOT + # Install the PILOT package from PyPI + pip install pilotpy + pypi: pilotpy +tags: + - multi-omics + - single-cell + - trajectory + - pathomics-data + - ot + - patient-level +license: MIT +version: v2.0.6 +contact: + - mehdijoodaki + - minashaigan +test_command: | + conda create --name PILOT python=3.11.5 r-base + conda activate PILOT + pip install pilotpy + conda install pytest + cd test && pytest test_pilot.py +category: ecosystem diff --git a/packages/ParTIpy/meta.yaml b/packages/ParTIpy/meta.yaml new file mode 100644 index 00000000..19bbc425 --- /dev/null +++ b/packages/ParTIpy/meta.yaml @@ -0,0 +1,19 @@ +name: ParTIpy +description: | + Implements Pareto task inference and archetypal analysis for analyzing functional trade-offs in single-cell and spatial omics data. +project_home: https://github.com/saezlab/ParTIpy +documentation_home: https://partipy.readthedocs.io/en/latest/ +tutorials_home: https://partipy.readthedocs.io/en/latest/ +install: + pypi: partipy +license: MIT +tags: + - "single cell" + - "archetypal analysis" + - "division of labor" + - "representation learning" +version: v0.0.04 +contact: + - psl-schaefer + - leotenshii +category: ecosystem diff --git a/packages/PathML/meta.yaml b/packages/PathML/meta.yaml new file mode 100644 index 00000000..49553080 --- /dev/null +++ b/packages/PathML/meta.yaml @@ -0,0 +1,27 @@ +name: PathML +description: | + An open-source toolkit for computational pathology and machine learning. +project_home: https://pathml.org/ +documentation_home: https://pathml.readthedocs.io/en/latest/ +tutorials_home: https://pathml.readthedocs.io/en/latest/ +publications: + - 10.1158/1541-7786.MCR-21-0665 +install: + pypi: pathml +tags: + - pathology +license: GPL-2.0-only +version: v2.1.0 +contact: + - jacob-rosenthal + - ryanccarelli + - BeeGass + - MohamedOmar2020 + - Karenxzr + - ella-dfci + - surya-narayanan + - dmbrundage + - Yu-AnChen + - jzhang1031 +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/PyDESeq2/meta.yaml b/packages/PyDESeq2/meta.yaml new file mode 100644 index 00000000..0f1d9156 --- /dev/null +++ b/packages/PyDESeq2/meta.yaml @@ -0,0 +1,23 @@ +name: PyDESeq2 +description: | + PyDESeq2 is a python package for bulk RNA-seq differential expression analysis. It is a re-implementation + from scratch of the main features of the R package DESeq2 (Love et al. 2014). +project_home: https://github.com/owkin/PyDESeq2 +documentation_home: https://pydeseq2.readthedocs.io +tutorials_home: https://pydeseq2.readthedocs.io/en/latest/auto_examples/index.html +install: + pypi: pydeseq2 +license: MIT +tags: + - rna-seq + - differential-expression +publications: + - 10.1101/2022.12.14.520412 +version: v0.3.0 +contact: + - BorisMuzellec + - maikia + - vcabeli +test_command: | + pip install ."[dev]" && pytest +category: ecosystem diff --git a/packages/Rectangle/meta.yaml b/packages/Rectangle/meta.yaml new file mode 100644 index 00000000..10456308 --- /dev/null +++ b/packages/Rectangle/meta.yaml @@ -0,0 +1,19 @@ +name: Rectangle +description: | + Rectangle is a python package for computational deconvolution. + Rectangle presents a novel approach to second-generation deconvolution, characterized by hierarchical processing, an estimation of unknown cellular content and a significant reduction in data volume during signature matrix computation. +project_home: https://github.com/ComputationalBiomedicineGroup/Rectangle +documentation_home: https://rectanglepy.readthedocs.io +tutorials_home: https://rectanglepy.readthedocs.io/notebooks/example.html +install: + pypi: rectanglepy +license: MIT +tags: + - rna-seq + - deconvolution +version: v0.1.6 +contact: + - bernheder +test_command: | + pip install ."[dev,test]" && pytest +category: ecosystem diff --git a/packages/SC2Spa/meta.yaml b/packages/SC2Spa/meta.yaml new file mode 100644 index 00000000..53687c5e --- /dev/null +++ b/packages/SC2Spa/meta.yaml @@ -0,0 +1,23 @@ +name: SC2Spa +description: | + SC2Spa is a deep learning-based tool for predicting the spatial coordinates of single cells based on transcriptome. + Two paired single cell and spatial transcriptomic datasets are required to run SC2Spa. SC2Spa is trained on a ST reference + dataset to learn the relationship of gene expression and spatial coordinates. The trained fully-connected neural network + can be used to predict the locations of a single cell with only the transcriptomic profile as input. The predicted locations + of single cells can be further used to study the communication of the single cells. +project_home: https://github.com/linbuliao/SC2Spa +documentation_home: https://sc2spa.readthedocs.io/ +install: + pypi: SC2Spa +tags: + - spatial inference + - scRNA-seq + - spatial transcriptomics + - deep learning + - cell communication +license: BSD-3-Clause +version: v1.2 +contact: + - linbuliao +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/SCALEX/meta.yaml b/packages/SCALEX/meta.yaml new file mode 100644 index 00000000..25e442b6 --- /dev/null +++ b/packages/SCALEX/meta.yaml @@ -0,0 +1,20 @@ +name: SCALEX +description: | + SCALEX is an integration and projection tool for atlas-level single-cell RNA-seq and ATAC-seq data. +project_home: https://github.com/jsxlei/SCALEX +documentation_home: https://scalex.readthedocs.io/en/latest/?badge=stable +publications: + - 10.1038/s41467-022-33758-z +install: + pypi: SCALEX +tags: + - scRNA-seq + - integration + - projection + - scATAC-seq +license: MIT +version: v1.0.3 +contact: + - jsxlei +test_command: pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/STMiner/meta.yaml b/packages/STMiner/meta.yaml new file mode 100644 index 00000000..f2a0e45f --- /dev/null +++ b/packages/STMiner/meta.yaml @@ -0,0 +1,18 @@ +name: STMiner +description: | + Gene-centric spatial transcriptomics for deciphering complex spatial omics data +project_home: https://github.com/xjtu-omics/STMiner +documentation_home: https://stminerdoc.readthedocs.io/en/latest +install: + pypi: stminer +tags: + - spatial variable genes + - spatial patterns + - optimal transport + - mechine learning +license: GPL-3.0-or-later +version: v1.1.0 +contact: + - PSSUN +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/SnapATAC2/logo.svg b/packages/SnapATAC2/logo.svg new file mode 100644 index 00000000..6bd807cc --- /dev/null +++ b/packages/SnapATAC2/logo.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + ® + diff --git a/packages/SnapATAC2/meta.yaml b/packages/SnapATAC2/meta.yaml new file mode 100644 index 00000000..dd9fa019 --- /dev/null +++ b/packages/SnapATAC2/meta.yaml @@ -0,0 +1,24 @@ +name: SnapATAC2 +description: | + SnapATAC2 is a scalable and modular pipeline for analyzing single-cell ATAC-seq data, + enabling efficient preprocessing, dimensionality reduction, clustering, and integration + with single-cell RNA-seq. +project_home: https://github.com/scverse/SnapATAC2 +documentation_home: https://scverse.org/SnapATAC2/ +tutorials_home: https://scverse.org/SnapATAC2/tutorials/index.html +publications: + - 10.1038/s41592-023-02139-9 +install: + pypi: snapatac2 + conda: bioconda::snapatac2 +tags: + - ATAC-seq + - chromatin accessibility + - epigenomics +license: MIT +version: 2.5.0 +contact: + - kaizhang +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/TreeData/meta.yaml b/packages/TreeData/meta.yaml new file mode 100644 index 00000000..16fa697d --- /dev/null +++ b/packages/TreeData/meta.yaml @@ -0,0 +1,17 @@ +name: TreeData +description: | + TreeData is a lightweight wrapper around AnnData which adds two additional attributes, obst and vart, + to store nx.DiGraph trees for observations and variables. +project_home: https://github.com/YosefLab/treedata +documentation_home: https://treedata.readthedocs.io/en/latest/ +tutorials_home: https://treedata.readthedocs.io/en/latest/ +install: + pypi: treedata +tags: + - lineage-tracing +license: BSD-3-Clause +version: v0.2.2 +contact: + - colganwi +test_command: pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/anndata-for-R/meta.yaml b/packages/anndata-for-R/meta.yaml new file mode 100644 index 00000000..cfceb042 --- /dev/null +++ b/packages/anndata-for-R/meta.yaml @@ -0,0 +1,21 @@ +name: anndata for R +description: | + **⚠️ DEPRECATED: This package is deprecated in favor of anndataR. Please use + anndataR for new projects.** + + A 'reticulate' wrapper for the Python package 'anndata'. Provides a scalable way + of keeping track of data and learned annotations. Used to read from and write to + the h5ad file format. +project_home: https://github.com/dynverse/anndata +documentation_home: https://anndata.dynverse.org +install: + cran: anndata +tags: + - data structures + - interoperability + - R +license: MIT +version: 0.7.5.5 +contact: + - rcannood +category: ecosystem diff --git a/packages/anndata/logo.svg b/packages/anndata/logo.svg new file mode 100644 index 00000000..92fe74ed --- /dev/null +++ b/packages/anndata/logo.svg @@ -0,0 +1 @@ + diff --git a/packages/anndata/meta.yaml b/packages/anndata/meta.yaml new file mode 100644 index 00000000..d3e5e31a --- /dev/null +++ b/packages/anndata/meta.yaml @@ -0,0 +1,24 @@ +name: AnnData +description: | + anndata is a Python package for handling annotated data matrices in memory and on disk, + positioned between pandas and xarray. anndata offers a broad range of computationally + efficient features including, among others, sparse data support, lazy operations, and GPU support. +project_home: https://github.com/scverse/anndata +documentation_home: https://anndata.readthedocs.io/en/latest/ +tutorials_home: https://anndata.readthedocs.io/en/latest/tutorials/index.html +publications: + - 10.1101/2021.12.16.473007 +install: + pypi: anndata + conda: conda-forge::anndata +tags: + - data structure + - annotated data + - sparse data +license: BSD-3-Clause +version: 0.12.4 +contact: + - flying-sheep + - ilan-gold +logo: logo.svg +category: core-datastructure diff --git a/packages/anndataR/logo.svg b/packages/anndataR/logo.svg new file mode 100644 index 00000000..568b20f9 --- /dev/null +++ b/packages/anndataR/logo.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + anndataR + + + diff --git a/packages/anndataR/meta.yaml b/packages/anndataR/meta.yaml new file mode 100644 index 00000000..bb369d32 --- /dev/null +++ b/packages/anndataR/meta.yaml @@ -0,0 +1,24 @@ +name: anndataR +description: | + An R implementation of the AnnData object including native reading and writing + of H5AD files and conversion to common R data structures. +project_home: https://github.com/scverse/anndataR +documentation_home: https://bioconductor.org/packages/anndataR/ +tutorials_home: https://anndatar.data-intuitive.com/ +install: + bioconductor: anndataR +license: MIT +tags: + - data structures + - interoperability + - R + - Bioconductor +publications: + - 10.1101/2025.08.18.669052 # bioRxiv preprint +version: 1.0.0 +contact: + - lazappi + - rcannood + - LouiseDck +logo: logo.svg +category: ecosystem diff --git a/packages/annsel/meta.yaml b/packages/annsel/meta.yaml new file mode 100644 index 00000000..016dbf5c --- /dev/null +++ b/packages/annsel/meta.yaml @@ -0,0 +1,21 @@ +name: annsel +description: | + Annsel is a user-friendly library that brings familiar dataframe-style operations to AnnData objects such as + selection, filtering and group by's. +project_home: https://github.com/srivarra/annsel +documentation_home: https://annsel.readthedocs.io/en/latest/ +tutorials_home: https://annsel.readthedocs.io/en/latest/notebooks/all_of_annsel.html +install: + pypi: annsel +license: MIT +version: v0.0.8 +contact: + - srivarra +tags: + - narwhals + - dataframe + - accessor + - utilities +test_command: | + pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/benGRN/meta.yaml b/packages/benGRN/meta.yaml new file mode 100644 index 00000000..dc768cb1 --- /dev/null +++ b/packages/benGRN/meta.yaml @@ -0,0 +1,21 @@ +name: benGRN +description: | + Benchmarking tool for gene network inference from single cell RNAseq methods. + It uses the grnndata/anndata modality and only contains biological ground truth networks +project_home: https://github.com/jkobject/benGRN +documentation_home: https://www.jkobject.com/benGRN +publications: + - 10.1101/2024.07.29.605556 +install: + pypi: bengrn +tags: + - single cell + - RNAseq + - gene network inference + - benchmark +license: MIT +version: v1.2.1 +contact: + - jkobject +test_command: pip install . && make test +category: ecosystem diff --git a/packages/bento-tools/meta.yaml b/packages/bento-tools/meta.yaml new file mode 100644 index 00000000..f2799175 --- /dev/null +++ b/packages/bento-tools/meta.yaml @@ -0,0 +1,19 @@ +name: bento-tools +description: | + A Python toolkit for subcellular analysis of spatial transcriptomics data +project_home: https://github.com/ckmah/bento-tools +documentation_home: https://bento-tools.readthedocs.io/en/latest/ +tutorials_home: https://bento-tools.readthedocs.io/en/latest/tutorials.html +publications: + - 10.1101/2022.06.10.495510 +install: + pypi: bento-tools +tags: + - spatial analysis +license: BSD-2-Clause +version: v1.0.1 +contact: + - ckmah + - noor01 +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/biolord/meta.yaml b/packages/biolord/meta.yaml new file mode 100644 index 00000000..646dffa3 --- /dev/null +++ b/packages/biolord/meta.yaml @@ -0,0 +1,19 @@ +name: biolord +description: | + biolord (biological representation disentanglement) is a deep generative framework for disentangling known and unknown attributes in single-cell data. +project_home: https://github.com/nitzanlab/biolord +documentation_home: https://biolord.readthedocs.io +tutorials_home: https://biolord.readthedocs.io +install: + pypi: biolord +tags: + - single-cell + - disentanglement + - generative framework +license: BSD-3-Clause +version: v0.0.1 +contact: + - zoepiran +test_command: | + pip install ".[dev,test]" && pytest +category: ecosystem diff --git a/packages/cell2location/meta.yaml b/packages/cell2location/meta.yaml new file mode 100644 index 00000000..297cc961 --- /dev/null +++ b/packages/cell2location/meta.yaml @@ -0,0 +1,25 @@ +name: cell2location +description: | + Cell2location is a Bayesian model that can resolve fine-grained cell types in spatial transcriptomic data + and create comprehensive cellular maps of diverse tissues. Cell2location accounts for technical sources + of variation and borrows statistical strength across locations, thereby enabling the integration of single-cell + and spatial transcriptomics with higher sensitivity and resolution than existing tools. +project_home: https://github.com/BayraktarLab/cell2location +documentation_home: https://cell2location.readthedocs.io/en/latest/ +tutorials_home: https://cell2location.readthedocs.io/en/latest/ +publications: + - 10.1038/s41587-021-01139-4 +install: + pypi: cell2location +tags: + - Bayesian +license: Apache-2.0 +version: v0.1 +contact: + - vitkl + - yozhikoff + - mayerdev + - emdann +test_command: | + pip install ".[dev]" && pytest +category: ecosystem diff --git a/packages/cellxgene/meta.yaml b/packages/cellxgene/meta.yaml new file mode 100644 index 00000000..b3900017 --- /dev/null +++ b/packages/cellxgene/meta.yaml @@ -0,0 +1,30 @@ +name: cellxgene +description: | + CZ CELLxGENE Annotate (pronounced "cell-by-gene") is an interactive data explorer for single-cell datasets, + such as those coming from the Human Cell Atlas. +project_home: https://github.com/chanzuckerberg/cellxgene +documentation_home: https://docs.cellxgene.cziscience.com/ +publications: + - 10.1101/2021.04.05.438318 +install: + pypi: cellxgene +tags: + - HCA +license: MIT +version: 1.1.1 +contact: + - csweaver + - bkmartinjr + - seve + - maniarathi + - atolopko-czi + - mckinsel + - MDunitz + - colinmegill + - blrnw3 + - freeman-lab + - bmccandless + - mweiden +test_command: | + pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/cookiecutter-scverse/meta.yaml b/packages/cookiecutter-scverse/meta.yaml new file mode 100644 index 00000000..7bb48a6a --- /dev/null +++ b/packages/cookiecutter-scverse/meta.yaml @@ -0,0 +1,14 @@ +name: cookiecutter-scverse +description: | + Cookiecutter template for scverse packages offering automated template sync +project_home: https://github.com/scverse/cookiecutter-scverse +documentation_home: https://cookiecutter-scverse-instance.readthedocs.io/en/latest/template_usage.html +tags: + - template + - cookiecutter +license: BSD-3-Clause +version: 0.6.0 +contact: + - grst + - flying-sheep +category: core-infrastructure diff --git a/packages/dandelion/meta.yaml b/packages/dandelion/meta.yaml new file mode 100644 index 00000000..bfa99e76 --- /dev/null +++ b/packages/dandelion/meta.yaml @@ -0,0 +1,28 @@ +name: dandelion +description: | + dandelion - A single cell BCR/TCR V(D)J-seq analysis package for 10X Chromium 5' data. + It streamlines the pre-processing, leveraging some tools from immcantation suite, and + integrates with scanpy/anndata for single-cell BCR/TCR analysis. It also includes a + couple of functions for visualization. +project_home: https://github.com/zktuong/dandelion +documentation_home: https://sc-dandelion.readthedocs.io/en/latest/ +tutorials_home: https://sc-dandelion.readthedocs.io/en/latest/ +publications: + - 10.1038/s41591-021-01329-2 + - 10.1101/2022.11.18.517068 +install: + pypi: sc-dandelion +tags: + - dandelion + - bcr + - tcr +license: AGPL-3.0-or-later +version: v0.3.0 +contact: + - zktuong + - ktpolanski + - suochenqu + - grst +test_command: | + pip install "." && pytest +category: ecosystem diff --git a/packages/decoupler/logo.svg b/packages/decoupler/logo.svg new file mode 100644 index 00000000..03a4b0e9 --- /dev/null +++ b/packages/decoupler/logo.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/decoupler/meta.yaml b/packages/decoupler/meta.yaml new file mode 100644 index 00000000..039c6e6b --- /dev/null +++ b/packages/decoupler/meta.yaml @@ -0,0 +1,24 @@ +name: decoupler +description: | + decoupler is a framework containing different enrichment statistical methods to extract + biologically driven scores from omics data within a unified framework. +project_home: https://github.com/scverse/decoupler +documentation_home: https://decoupler.readthedocs.io/en/latest/ +tutorials_home: https://decoupler.readthedocs.io/en/latest/notebooks/index.html +publications: + - 10.1093/bioadv/vbac016 +install: + pypi: decoupler + conda: conda-forge::decoupler-py +tags: + - enrichment analysis + - pathway analysis + - gene sets + - functional annotation +license: BSD-3-Clause +version: 2.1.1 +contact: + - PauBadiaM +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/delnx/meta.yaml b/packages/delnx/meta.yaml new file mode 100644 index 00000000..ec060be2 --- /dev/null +++ b/packages/delnx/meta.yaml @@ -0,0 +1,21 @@ +name: delnx +description: | + delnx is a python package for differential expression analysis of (single-cell) genomics data. It enables scalable analyses of atlas-level datasets through GPU-accelerated regression models and statistical tests implemented in JAX and provides a consistent interface to perform DE analysis with other methods, such as statsmodels and PyDESeq2. +project_home: https://github.com/joschif/delnx +documentation_home: https://delnx.readthedocs.io/en/latest/ +tutorials_home: https://delnx.readthedocs.io/en/latest/ +install: + pypi: delnx +tags: + - differential expression + - regression models + - dispersion estimation + - JAX +license: MIT +version: v0.2.3 +contact: + - joschif + - adaml9 +test_command: | + pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/dynamo-release/meta.yaml b/packages/dynamo-release/meta.yaml new file mode 100644 index 00000000..5c761c99 --- /dev/null +++ b/packages/dynamo-release/meta.yaml @@ -0,0 +1,22 @@ +name: dynamo-release +description: | + Inclusive model of expression dynamics with metabolic labeling based scRNA-seq / multiomics, + vector field reconstruction, potential landscape mapping, differential geometry analyses, + and most probably paths / in silico perturbation predictions. +project_home: https://github.com/aristoteleo/dynamo-release +documentation_home: https://dynamo-release.readthedocs.io/en/latest/ +tutorials_home: https://dynamo-release.readthedocs.io/en/latest/ +publications: + - 10.1016/j.cell.2021.12.045 +install: + pypi: dynamo-release +tags: + - vector +license: BSD-3-Clause +version: v1.1.0 +contact: + - Xiaojieqiu + - dummyindex + - yaz62 +test_command: pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/ecosystem-packages/meta.yaml b/packages/ecosystem-packages/meta.yaml new file mode 100644 index 00000000..84b3c4af --- /dev/null +++ b/packages/ecosystem-packages/meta.yaml @@ -0,0 +1,13 @@ +name: ecosystem-packages +description: | + Registry for scverse ecosystem packages (https://scverse.org/packages/#ecosystem) +project_home: https://github.com/scverse/ecosystem-packages +documentation_home: https://github.com/scverse/ecosystem-packages +tags: + - registry + - ecosystem +license: BSD-3-Clause +contact: + - grst + - flying-sheep +category: core-infrastructure diff --git a/packages/epiScanpy/meta.yaml b/packages/epiScanpy/meta.yaml new file mode 100644 index 00000000..2c60044d --- /dev/null +++ b/packages/epiScanpy/meta.yaml @@ -0,0 +1,27 @@ +name: epiScanpy +description: | + EpiScanpy is a toolkit to analyse single-cell open chromatin (scATAC-seq) and single-cell + DNA methylation (for example scBS-seq) data. +project_home: https://github.com/colomemaria/epiScanpy +documentation_home: https://episcanpy.readthedocs.io/en/latest/ +tutorials_home: https://episcanpy.readthedocs.io/en/latest/ +publications: + - 10.1038/s41467-021-25131-3 +install: + pypi: episcanpy +tags: + - scanpy + - epigenomics +license: BSD-3-Clause +version: v0.3.2 +contact: + - DaneseAnna + - mrichter23 + - kridsadakorn + - rLannes + - le-ander + - HAL9032 + - michalk8 + - mvinyard +test_command: pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/eschr/meta.yaml b/packages/eschr/meta.yaml new file mode 100644 index 00000000..40ac20b5 --- /dev/null +++ b/packages/eschr/meta.yaml @@ -0,0 +1,21 @@ +name: eschr +description: | + ESCHR is an ensemble clustering method that provides hard clustering along with + uncertainty scores and soft clustering outputs for enhanced interpretability. +project_home: https://github.com/zunderlab/eschr +documentation_home: https://eschr.readthedocs.io/en/latest/ +tutorials_home: https://eschr.readthedocs.io/en/latest/notebooks/paul15_mouse_hematopoiesis.html +publications: + - 10.1186/s13059-024-03386-5 +install: + pypi: eschr +tags: + - clustering + - uncertainty + - ensemble +license: "MIT" +version: v1.0.1 +contact: + - smgoggin10 +test_command: pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/favapy/meta.yaml b/packages/favapy/meta.yaml new file mode 100644 index 00000000..56cbbf92 --- /dev/null +++ b/packages/favapy/meta.yaml @@ -0,0 +1,21 @@ +name: fava +description: | + FAVA uses Variational Autoencoders to infer functional associations from + large-scale scRNA-seq (and proteomics) data. +project_home: https://github.com/mikelkou/fava +documentation_home: https://github.com/mikelkou/fava/blob/main/README.md +tutorials_home: https://github.com/mikelkou/fava/blob/main/How_to_use_favapy_in_a_notebook.ipynb +publications: + - 10.1101/2022.07.06.499022 + - 10.1093/nar/gkac1000 +install: + pypi: favapy +tags: + - coexpression networks + - functional associations + - variational autoencoders +license: MIT +version: v0.3.9.4 +contact: + - mikelkou +category: ecosystem diff --git a/packages/flowsom/meta.yaml b/packages/flowsom/meta.yaml new file mode 100644 index 00000000..c8a9c457 --- /dev/null +++ b/packages/flowsom/meta.yaml @@ -0,0 +1,28 @@ +name: flowsom +description: | + The complete FlowSOM package known from R, now available in Python! + Analyze high-dimensional cytometry data using FlowSOM, + a clustering and visualization algorithm based on a self-organizing map (SOM). + FlowSOM is used to distinguish cell populations from cytometry data in an unsupervised way and + can help to gain deeper insights in fields such as immunology and oncology. +project_home: https://github.com/saeyslab/FlowSOM_Python +documentation_home: https://flowsom.readthedocs.io/en/latest/ +tutorials_home: https://flowsom.readthedocs.io/en/latest/notebooks/example.html +publications: + - 10.1093/bioinformatics/btae179 + - 10.1002/cyto.a.22625 + - 10.1038/s41596-021-00550-0 +install: + conda: conda-forge::flowsom +tags: + - clustering + - flowcytometry +license: GPL-3.0-only +version: v0.0.1 +contact: + - artuurC + - berombau + - ysaeys + - SofieVG +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/governance/meta.yaml b/packages/governance/meta.yaml new file mode 100644 index 00000000..f67f96a3 --- /dev/null +++ b/packages/governance/meta.yaml @@ -0,0 +1,14 @@ +name: governance +description: | + Governance docs for scverse +project_home: https://github.com/scverse/governance +documentation_home: https://scverse.org/about +tags: + - governance + - documentation +license: BSD-3-Clause +contact: + - Zethson + - gtca + - mikelkou +category: core-infrastructure diff --git a/packages/gssnng/meta.yaml b/packages/gssnng/meta.yaml new file mode 100644 index 00000000..6548cd02 --- /dev/null +++ b/packages/gssnng/meta.yaml @@ -0,0 +1,24 @@ +name: gssnng +description: | + Single-cell gene set scoring with nearest neighbor graph smoothed data. +project_home: https://github.com/IlyaLab/gssnng +documentation_home: https://gssnng.readthedocs.io/en/latest/ +tutorials_home: https://github.com/IlyaLab/gssnng/tree/main/notebooks +publications: + - 10.1093/bioadv/vbad150 +install: + pypi: gssnng +tags: + - scRNA-seq + - GSEA + - geneset-scoring + - smoothing + - python +license: MIT +version: v0.4.2 +contact: + - gibbsdavidl + - redst4r +test_command: | + git clone git@github.com:IlyaLab/gssnng.git && pip install gssnng && pip install pytest && cd gssnng/ && pytest +category: ecosystem diff --git a/packages/hotspot/meta.yaml b/packages/hotspot/meta.yaml new file mode 100644 index 00000000..d86d5a3e --- /dev/null +++ b/packages/hotspot/meta.yaml @@ -0,0 +1,20 @@ +name: hotspot +description: | + Hotspot is a tool for identifying informative genes (and gene modules) in a single-cell dataset. +project_home: https://github.com/yoseflab/hotspot +documentation_home: https://hotspot.readthedocs.io/en/latest/ +tutorials_home: https://hotspot.readthedocs.io/en/latest/ +publications: + - 10.1016/j.cels.2021.04.005 +install: + pypi: hotspotsc +tags: + - gene-signatures +license: BSD-3-Clause +version: v1.1.1 +contact: + - deto + - adamgayoso +test_command: | + pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/illico/meta.yaml b/packages/illico/meta.yaml new file mode 100644 index 00000000..7b6472c4 --- /dev/null +++ b/packages/illico/meta.yaml @@ -0,0 +1,19 @@ +name: illico +description: | + illico runs fast, CPU-based, wilcoxon rank-sum tests to identify differentially expressed genes for single-cell RNA-seq data. +project_home: https://github.com/remydubois/illico +documentation_home: https://github.com/remydubois/illico +tutorials_home: https://github.com/remydubois/illico +publications: [] +install: + pypi: illico +tags: + - differential-gene-expression + - single-cell-RNA-seq +license: Apache-2.0 +version: 0.1.1 +contact: + - remydubois +test_command: | + tox -e unit-tests +category: ecosystem diff --git a/packages/infercnvpy/meta.yaml b/packages/infercnvpy/meta.yaml new file mode 100644 index 00000000..383d925c --- /dev/null +++ b/packages/infercnvpy/meta.yaml @@ -0,0 +1,17 @@ +name: infercnvpy +description: | + Infer copy number variation (CNV) from scRNA-seq data. Plays nicely with Scanpy. +project_home: https://github.com/icbi-lab/infercnvpy +documentation_home: https://infercnvpy.readthedocs.io/en/latest/ +tutorials_home: https://infercnvpy.readthedocs.io/en/latest/tutorials.html +install: + pypi: infercnvpy +tags: + - CNV +license: BSD-3-Clause +version: v0.3.0 +contact: + - grst +test_command: | + pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/integration-testing/meta.yaml b/packages/integration-testing/meta.yaml new file mode 100644 index 00000000..4e4a49b3 --- /dev/null +++ b/packages/integration-testing/meta.yaml @@ -0,0 +1,13 @@ +name: integration-testing +description: | + A repo for integration testing core packages against upstream core packages +project_home: https://github.com/scverse/integration-testing +documentation_home: https://github.com/scverse/integration-testing +tags: + - testing + - continuous integration +license: MIT +contact: + - ilan-gold + - flying-sheep +category: core-infrastructure diff --git a/packages/kompot/logo.png b/packages/kompot/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..afaea224e21dc69d195d586f1f83becaf0131466 GIT binary patch literal 138271 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 { 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/mudata/meta.yaml b/packages/mudata/meta.yaml new file mode 100644 index 00000000..9f32d916 --- /dev/null +++ b/packages/mudata/meta.yaml @@ -0,0 +1,24 @@ +name: MuData +description: | + MuData is a format for annotated multimodal datasets where each modality is represented + by an AnnData object. MuData's reference implementation is in Python, and the cross-language + functionality is achieved via HDF5-based .h5mu files with libraries in R and Julia. +project_home: https://github.com/scverse/mudata +documentation_home: https://mudata.readthedocs.io/en/latest/ +tutorials_home: https://mudata.readthedocs.io/en/latest/notebooks/quickstart_mudata.html +publications: + - 10.1186/s13059-021-02577-8 +install: + pypi: mudata + conda: conda-forge::mudata +tags: + - data structure + - multimodal + - multi-omics +license: BSD-3-Clause +version: 0.3.2 +contact: + - gtca + - ilia-kats +logo: logo.svg +category: core-datastructure diff --git a/packages/muon/logo.svg b/packages/muon/logo.svg new file mode 100644 index 00000000..93523a54 --- /dev/null +++ b/packages/muon/logo.svg @@ -0,0 +1 @@ + diff --git a/packages/muon/meta.yaml b/packages/muon/meta.yaml new file mode 100644 index 00000000..8b6a41da --- /dev/null +++ b/packages/muon/meta.yaml @@ -0,0 +1,23 @@ +name: Muon +description: | + muon is a Python framework for multimodal omics analysis. It provides functionality + for working with multimodal data, including preprocessing, integration, and visualization. +project_home: https://github.com/scverse/muon +documentation_home: https://muon.readthedocs.io/en/latest/ +tutorials_home: https://muon-tutorials.readthedocs.io/en/latest/ +publications: + - 10.1186/s13059-021-02577-8 +install: + pypi: muon + conda: conda-forge::muon +tags: + - multimodal + - multi-omics + - integration +license: BSD-3-Clause +version: 0.1.7 +contact: + - gtca +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/novae/meta.yaml b/packages/novae/meta.yaml new file mode 100644 index 00000000..ed19c3bc --- /dev/null +++ b/packages/novae/meta.yaml @@ -0,0 +1,21 @@ +name: novae +description: | + Graph-based foundation model for spatial transcriptomics data. + Zero-shot spatial domain inference, batch-effect correction, and many other features. +project_home: https://github.com/MICS-Lab/novae +documentation_home: https://mics-lab.github.io/novae/ +publications: + - 10.1101/2024.09.09.612009 +install: + pypi: novae +tags: + - spatial-omics + - spatial-transcriptomics + - spatialdata + - deep learning +license: BSD-3-Clause +version: v0.2.1 +contact: + - quentinblampey +test_command: pip install ".[dev]" && pytest +category: ecosystem diff --git a/packages/omicverse/meta.yaml b/packages/omicverse/meta.yaml new file mode 100644 index 00000000..92db0dba --- /dev/null +++ b/packages/omicverse/meta.yaml @@ -0,0 +1,24 @@ +name: omicverse +description: | + OmicVerse is the fundamental package for multi omics included bulk and single cell analysis with Python. + The original name of the omicverse was Pyomic, but we wanted to address a whole universe of transcriptomics, + so we changed the name to OmicVerse, it aimed to solve all task in RNA-seq. +project_home: https://github.com/Starlitnightly/omicverse +documentation_home: https://omicverse.readthedocs.io/ +publications: + - 10.1101/2023.06.06.543913 +install: + pypi: omicverse +tags: + - single-cell + - bulk-rna-seq + - omics + - bioinformatics +license: GPL-3.0-only +version: v1.4.12 +contact: + - Starlitnightly + - DBinary + - JuliaMYQ +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/palantir/meta.yaml b/packages/palantir/meta.yaml new file mode 100644 index 00000000..17bb6419 --- /dev/null +++ b/packages/palantir/meta.yaml @@ -0,0 +1,33 @@ +name: Palantir +description: | + Palantir is an algorithm to align cells along differentiation trajectories. + Palantir models differentiation as a stochastic process where stem cells + differentiate to terminally differentiated cells by a series of steps through + a low dimensional phenotypic manifold. Palantir effectively captures the + continuity in cell states and the stochasticity in cell fate determination. + Palantir has been designed to work with multidimensional single cell data from + diverse technologies such as Mass cytometry and single cell RNA-seq. +project_home: https://github.com/dpeerlab/Palantir +documentation_home: https://palantir.readthedocs.io +publications: + - 10.1038/s41587-019-0068-4 +install: + pypi: palantir +tags: + - markov-chain + - dimensionality-reduction + - scrna-seq + - trajectory-generation + - diffusion-maps + - differentiation + - manifold-learning + - single-cell-genomics + - cell-fate-transitions + - scrna-seq-analysis +license: GPL-2.0-or-later +version: v1.3.3 +contact: + - ManuSetty + - katosh +test_command: pip install -e '.' && pip install flake8 pytest coverage typing-extensions && pytest +category: ecosystem diff --git a/packages/panpipes/meta.yaml b/packages/panpipes/meta.yaml new file mode 100644 index 00000000..17f2b343 --- /dev/null +++ b/packages/panpipes/meta.yaml @@ -0,0 +1,31 @@ +name: Panpipes +description: | + A pipeline for multiomic single-cell and spatial transcriptomic data analysis +project_home: https://github.com/DendrouLab/panpipes +documentation_home: https://panpipes-pipelines.readthedocs.io/en/latest/index.html +tutorials_home: https://panpipes-pipelines.readthedocs.io/en/latest/tutorials/index.html +publications: + - 10.1101/2023.03.11.532085 +install: + pypi: panpipes +tags: + - single-cell + - multiomics + - pipeline + - spatial + - bioinformatics +license: BSD-3-Clause +version: v0.5.0 +contact: + - bio-la + - crichgriffin + - SarahOuologuem + - giuliaelgarcia + - kevinrue + - deevdevil88 + - Lilly-May + - tomthomas3000 + - Zethson + - wlason +test_command: pip install -e '.[dev]' && pytest +category: ecosystem diff --git a/packages/pcdl/meta.yaml b/packages/pcdl/meta.yaml new file mode 100644 index 00000000..cfdd8267 --- /dev/null +++ b/packages/pcdl/meta.yaml @@ -0,0 +1,30 @@ +name: pcdl +description: physicell data output loader for downstream data analysis in python3. +project_home: https://github.com/elmbeech/physicelldataloader +documentation_home: https://github.com/elmbeech/physicelldataloader/blob/master/README.md +tutorials_home: https://github.com/elmbeech/physicelldataloader/blob/master/man/TUTORIAL_python3_scverse.md +install: + pypi: pcdl +license: BSD-3-Clause +tags: + - python3 + - downstream data analysis + - physicell + - multicellular system + - agent-based modeling + - diffusion transport solver + - newtonian physics +#publications: +version: v4.0.4 +category: ecosystem +contact: + - ASundus + - elmbeech + - engjen + - furkankurtoglu + - godzilla-but-nice + - heberlr + - johnmetzcar + - MathCancer + - rheiland +test_command: pip install . && pytest test/ diff --git a/packages/pegasus/meta.yaml b/packages/pegasus/meta.yaml new file mode 100644 index 00000000..a56b5f1d --- /dev/null +++ b/packages/pegasus/meta.yaml @@ -0,0 +1,27 @@ +name: pegasus +description: | + Pegasus is a tool for analyzing transcriptomes of millions of single cells. +project_home: https://github.com/lilab-bcb/pegasus +documentation_home: https://pegasus.readthedocs.io/en/stable/ +tutorials_home: https://pegasus.readthedocs.io/en/stable/tutorials.html +publications: + - 10.1038/s41592-020-0905-x +install: + pypi: pegasuspy +tags: + - transcriptome analysis +license: BSD-3-Clause +version: v1.7.1 +contact: + - yihming + - bli25 + - YanayRosen + - rocherroche + - jshleap + - tariqdaouda + - hoondy + - joshua-gould + - slowkow + - jlchang +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/pertpy/logo.svg b/packages/pertpy/logo.svg new file mode 100644 index 00000000..0ca3d533 --- /dev/null +++ b/packages/pertpy/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/pertpy/meta.yaml b/packages/pertpy/meta.yaml new file mode 100644 index 00000000..d4c23e5b --- /dev/null +++ b/packages/pertpy/meta.yaml @@ -0,0 +1,25 @@ +name: Pertpy +description: | + Pertpy is a framework for analyzing large-scale single-cell perturbation experiments. + It harmonizes datasets, automates metadata annotation, calculates perturbation distances, + and analyzes cellular responses to genetic modifications, drugs, and environmental changes. +project_home: https://github.com/scverse/pertpy +documentation_home: https://pertpy.readthedocs.io/en/stable/ +tutorials_home: https://pertpy.readthedocs.io/en/stable/tutorials.html +publications: + - 10.1101/2024.08.04.606516 +install: + pypi: pertpy + conda: conda-forge::pertpy +tags: + - perturbation + - drug response + - CRISPR + - genetic perturbation +license: MIT +version: 1.0.3 +contact: + - Zethson +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/popV/meta.yaml b/packages/popV/meta.yaml new file mode 100644 index 00000000..5793656b --- /dev/null +++ b/packages/popV/meta.yaml @@ -0,0 +1,17 @@ +name: popV +description: | + p(opular)V(oting) is a consensus tool for transfering labels from an annotated reference dataset to an unannotated query dataset. Consensus calling allows interpretable scores that quantify certainty. +project_home: https://github.com/YosefLab/popV +documentation_home: https://popv.readthedocs.io/en/latest/ +install: + pypi: popv +tags: + - cell type labels + - batch integration + - automatic annotation +license: MIT +version: v0.5.2 +contact: + - canergen +test_command: pip install -e '.[test]' && pytest +category: ecosystem diff --git a/packages/pyLemur/meta.yaml b/packages/pyLemur/meta.yaml new file mode 100644 index 00000000..499e2607 --- /dev/null +++ b/packages/pyLemur/meta.yaml @@ -0,0 +1,20 @@ +name: pyLemur +description: | + Python implementation of the LEMUR algorithm for analyzing multi-condition single-cell RNA-seq data.. +project_home: https://github.com/const-ae/pyLemur +documentation_home: https://pyLemur.readthedocs.io +tutorials_home: https://pylemur.readthedocs.io/page/notebooks/Tutorial.html +publications: + - 10.1101/2023.03.06.531268 +install: + pypi: pyLemur +tags: + - single-cell + - differential expression + - multi-condition +license: MIT +version: v0.1.0 +contact: + - const-ae +test_command: pip install -e '.[dev]' && pytest +category: ecosystem diff --git a/packages/pySCENIC/meta.yaml b/packages/pySCENIC/meta.yaml new file mode 100644 index 00000000..b98dac82 --- /dev/null +++ b/packages/pySCENIC/meta.yaml @@ -0,0 +1,32 @@ +name: pySCENIC +description: | + pySCENIC is a lightning-fast python implementation of the SCENIC pipeline + (Single-Cell rEgulatory Network Inference and Clustering) which enables + biologists to infer transcription factors, gene regulatory networks and + cell types from single-cell RNA-seq data. +project_home: https://github.com/aertslab/pySCENIC +documentation_home: https://pyscenic.readthedocs.io/en/latest/ +tutorials_home: https://pyscenic.readthedocs.io/en/latest/tutorial.html +publications: + - 10.1038/nmeth.4463 + - 10.1371/journal.pone.0012776 + - 10.1038/s41596-020-0336-2 +install: + pypi: pyscenic +tags: + - regulatory networks + - clustering +license: GPL-3.0-only +version: v0.12.0 +contact: + - bramvds + - cflerin + - ghuls + - dweemx + - s-aibar + - cbravo93 + - pascal-git + - simonvh + - loremendez +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/pyUCell/meta.yaml b/packages/pyUCell/meta.yaml new file mode 100644 index 00000000..9865f231 --- /dev/null +++ b/packages/pyUCell/meta.yaml @@ -0,0 +1,26 @@ +name: pyUCell +description: | + pyUCell is a package for evaluating gene signatures in single-cell datasets. + pyUCell signature scores, based on the Mann-Whitney U statistic, are robust + to dataset size and heterogeneity, and their calculation demands less + computing time and memory than other available methods, enabling the + processing of large datasets in a few minutes even on machines with limited + computing power. +project_home: https://github.com/carmonalab/pyucell +documentation_home: https://pyucell.readthedocs.io/en/latest +tutorials_home: https://pyucell.readthedocs.io/en/latest/notebooks/basic.html +publications: + - 10.1016/j.csbj.2021.06.043 +install: + pypi: pyucell +tags: + - single-cell + - signature scoring + - module scoring +license: MIT +version: v0.3.0 +contact: + - mass-a + - sjcarmona +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/pycea/meta.yaml b/packages/pycea/meta.yaml new file mode 100644 index 00000000..aa526fab --- /dev/null +++ b/packages/pycea/meta.yaml @@ -0,0 +1,17 @@ +name: pycea +description: | + Pycea is a Python toolkit for single-cell lineage tracing analysis and visualization. +project_home: https://github.com/YosefLab/pycea +documentation_home: https://pycea.readthedocs.io/en/latest/ +tutorials_home: https://pycea.readthedocs.io/en/latest/ +install: + pypi: pycea-lineage +tags: + - lineage-tracing + - TreeData +license: BSD-3-Clause +version: v0.1.0 +contact: + - colganwi +test_command: pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/pychromVAR/meta.yaml b/packages/pychromVAR/meta.yaml new file mode 100644 index 00000000..1ca7a414 --- /dev/null +++ b/packages/pychromVAR/meta.yaml @@ -0,0 +1,18 @@ +name: pychromVAR +description: | + A python pacakge for chromVAR. +project_home: https://github.com/lzj1769/pychromVAR +documentation_home: https://pychromvar.readthedocs.io/en/latest/ +tutorials_home: https://pychromvar.readthedocs.io/en/latest/ +install: + pypi: pychromvar +tags: + - TF + - scATAC-seq +license: MIT +version: v0.0.3 +contact: + - lzj1769 +test_command: | + test_command: pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/pytximport/meta.yaml b/packages/pytximport/meta.yaml new file mode 100644 index 00000000..424627bd --- /dev/null +++ b/packages/pytximport/meta.yaml @@ -0,0 +1,21 @@ +name: pytximport +description: | + A Python port of the `tximport` R package for importing transcript-level quantification data from various RNA-seq quantification tools such as `salmon` and `kallisto` and summarizing it to the gene level. +project_home: https://github.com/complextissue/pytximport +documentation_home: https://pytximport.readthedocs.io/en/latest/ +tutorials_home: https://pytximport.readthedocs.io/en/latest/ +install: + pypi: pytximport +tags: + - rna-seq + - bulk-rna-seq + - differential-expression +license: GPL-3.0-only +version: v0.2.0 +contact: + - maltekuehl +test_command: | + pip install flit poetry && \ + flit install --deps all && \ + coverage run -m pytest +category: ecosystem diff --git a/packages/rapids-singlecell/logo.svg b/packages/rapids-singlecell/logo.svg new file mode 100644 index 00000000..e0fa8dfe --- /dev/null +++ b/packages/rapids-singlecell/logo.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + diff --git a/packages/rapids-singlecell/meta.yaml b/packages/rapids-singlecell/meta.yaml new file mode 100644 index 00000000..ce2c2e99 --- /dev/null +++ b/packages/rapids-singlecell/meta.yaml @@ -0,0 +1,21 @@ +name: rapids-singlecell +description: | + rapids-singlecell is a GPU-accelerated single-cell analysis library that serves as a + drop-in replacement for scanpy, squidpy, and decoupler. +project_home: https://github.com/scverse/rapids_singlecell +documentation_home: https://rapids-singlecell.readthedocs.io/en/latest/ +tutorials_home: https://rapids-singlecell.readthedocs.io/en/latest/notebooks.html +install: + pypi: rapids-singlecell +tags: + - GPU acceleration + - single-cell + - RAPIDS + - CUDA +license: MIT +version: 0.13.3 +contact: + - Intron7 +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/scCellFie/meta.yaml b/packages/scCellFie/meta.yaml new file mode 100644 index 00000000..8a63145e --- /dev/null +++ b/packages/scCellFie/meta.yaml @@ -0,0 +1,24 @@ +name: scCellFie +description: | + scCellFie infers metabolic activities from single-cell and spatial transcriptomics and offers a variety of downstream analyses. +project_home: https://github.com/earmingol/scCellFie +documentation_home: https://sccellfie.readthedocs.io +tutorials_home: https://sccellfie.readthedocs.io +install: + pypi: sccellfie +tags: + - single-cell + - spatial + - metabolism + - metabolic activities + - cell-cell communication +license: MIT +version: v0.4.5 +contact: + - earmingol +test_command: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + python -m pip install -e . + pytest -vv --cov --cov-report xml +category: ecosystem diff --git a/packages/scDataLoader/meta.yaml b/packages/scDataLoader/meta.yaml new file mode 100644 index 00000000..bb77545f --- /dev/null +++ b/packages/scDataLoader/meta.yaml @@ -0,0 +1,25 @@ +name: scDataLoader +description: | + A dataloader for large single cell databases like cellxgene. + Does weighted random sampling, downloading and preprocessing. + works with anndata, zarr, and h5ad files. +project_home: https://github.com/jkobject/scDataLoader +documentation_home: https://www.jkobject.com/scDataLoader/ +publications: + - 10.1101/2024.07.29.605556 +install: + pypi: scdataloader +tags: + - dataloader + - single cell + - RNAseq + - pytorch + - lightning + - cellxgene + - preprocessing +license: MIT +version: v1.2.2 +contact: + - jkobject +test_command: pip install . && make test +category: ecosystem diff --git a/packages/scFates/meta.yaml b/packages/scFates/meta.yaml new file mode 100644 index 00000000..ea8f7189 --- /dev/null +++ b/packages/scFates/meta.yaml @@ -0,0 +1,27 @@ +name: scFates +description: | + A scalable python package for tree inference and advanced pseudotime analysis from scRNAseq data. +project_home: https://github.com/LouisFaure/scFates +documentation_home: https://scfates.readthedocs.io/en/latest/ +tutorials_home: https://scfates.readthedocs.io/en/latest/Tree_Analysis_Bone_marrow_fates.html +publications: + - 10.1093/bioinformatics/btac746 +install: + pypi: scFates +tags: + - pseudotime + - cell-fate + - trajectory-generation +license: BSD-3-Clause +version: v1.0.0 +contact: + - LouisFaure +test_command: | + sudo apt-get clean && sudo apt-get update + sudo apt-get install -y r-base r-cran-mgcv + pip install wheel + pip install coverage cmake pytest mock + pip install rpy2==3.4.2 + pip install . + pytest scFates/tests/test_w_plots.py +category: ecosystem diff --git a/packages/scGen/meta.yaml b/packages/scGen/meta.yaml new file mode 100644 index 00000000..4e760fcd --- /dev/null +++ b/packages/scGen/meta.yaml @@ -0,0 +1,27 @@ +name: scGen +description: | + scGen is a generative model to predict single-cell perturbation response + across cell types, studies and species. +project_home: https://github.com/theislab/scgen +documentation_home: https://scgen.readthedocs.io/en/stable/ +tutorials_home: https://scgen.readthedocs.io/en/stable/tutorials/index.html +publications: + - 10.1038/s41592-019-0494-8 +install: + pypi: scgen +tags: + - perturbation +license: GPL-3.0-only +version: v2.1.0 +contact: + - M0hammadL + - adamgayoso + - Cottoneyejoe95 + - watiss + - ktpolanski + - Naghipourfar + - Zethson + - alirezaomidi + - mumichae +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/scLiTr/meta.yaml b/packages/scLiTr/meta.yaml new file mode 100644 index 00000000..60fe097c --- /dev/null +++ b/packages/scLiTr/meta.yaml @@ -0,0 +1,20 @@ +name: scLiTr +description: | + scLiTr (single-cell Lineage Tracing) is a python package for exploratory analysis of + barcoding-based scRNA-Seq lineage tracing experiments +project_home: https://github.com/kharchenkolab/scLiTr +documentation_home: https://sclitr.readthedocs.io/ +tutorials_home: https://sclitr.readthedocs.io/ +install: + pypi: sclitr +tags: + - label-transfer +license: MIT +publications: + - 10.1101/2024.11.15.623687 +version: v1.0.1 +contact: + - serjisa +test_command: | + pip install . && pytest +category: ecosystem diff --git a/packages/scPRINT/meta.yaml b/packages/scPRINT/meta.yaml new file mode 100644 index 00000000..ab50d3bf --- /dev/null +++ b/packages/scPRINT/meta.yaml @@ -0,0 +1,27 @@ +name: scPRINT +description: | + A single cell foundation model for Gene network inference and more... +project_home: https://github.com/cantinilab/scPRINT +documentation_home: https://cantinilab.github.io/scPRINT/ +publications: + - 10.1101/2024.07.29.605556 +install: + pypi: scprint +tags: + - foundation model + - single cell + - RNAseq + - gene network inference + - denoising + - zero imputation + - label prediction + - zero shot + - embedding + - pytorch + - lightning +license: MIT +version: v1.6.2 +contact: + - jkobject +test_command: pip install . && make test +category: ecosystem diff --git a/packages/scXpand/meta.yaml b/packages/scXpand/meta.yaml new file mode 100644 index 00000000..b0665c65 --- /dev/null +++ b/packages/scXpand/meta.yaml @@ -0,0 +1,26 @@ +name: scXpand +description: | + scXpand is a machine learning framework for pan-cancer detection of T-cell clonal expansion + directly from single-cell RNA sequencing (scRNA-seq), without paired T-cell receptor (TCR) sequencing. +project_home: https://github.com/yizhak-lab-ccg/scXpand +documentation_home: https://scxpand.readthedocs.io/en/latest/ +tutorials_home: https://scxpand.readthedocs.io/en/latest/ +publications: + - 10.1101/2025.09.14.676069 +install: + pypi: scxpand +tags: + - cancer + - scRNA-seq + - scTCR-seq + - T-cell clonal expansion + - machine learning +license: MIT +version: v0.4.3 +contact: + - ronamit + - ofirshorer + - yizhak-lab-ccg +test_command: | + pip install -e ".[dev]" && pytest --cov=src.scxpand tests +category: ecosystem diff --git a/packages/scanpro/meta.yaml b/packages/scanpro/meta.yaml new file mode 100644 index 00000000..8aec480f --- /dev/null +++ b/packages/scanpro/meta.yaml @@ -0,0 +1,20 @@ +name: scanpro +description: robust cell proportion analysis for single cell data +project_home: https://github.com/loosolab/scanpro +documentation_home: https://scanpro.readthedocs.io +tutorials_home: https://scanpro.readthedocs.io/en/latest/proportion_analysis.html +publications: + - 10.1101/2023.08.14.553234 +install: + pypi: scanpro +tags: + - single cell + - proportion analysis + - multi omics +license: MIT +version: 0.2.0 +contact: + - yalayoubi + - mlooso +test_command: pip install . && pytest +category: ecosystem diff --git a/packages/scanpy/logo.svg b/packages/scanpy/logo.svg new file mode 100644 index 00000000..20f9dc99 --- /dev/null +++ b/packages/scanpy/logo.svg @@ -0,0 +1 @@ + diff --git a/packages/scanpy/meta.yaml b/packages/scanpy/meta.yaml new file mode 100644 index 00000000..292bbeed --- /dev/null +++ b/packages/scanpy/meta.yaml @@ -0,0 +1,28 @@ +name: Scanpy +description: | + Scanpy is a scalable toolkit for analyzing single-cell gene expression data built jointly + with anndata. It includes preprocessing, visualization, clustering, trajectory inference + and differential expression testing. The Python-based implementation efficiently deals + with datasets of more than one million cells. +project_home: https://github.com/scverse/scanpy +documentation_home: https://scanpy.readthedocs.io/en/latest/ +tutorials_home: https://scanpy.readthedocs.io/en/latest/tutorials.html +publications: + - 10.1186/s13059-017-1382-0 +install: + pypi: scanpy + conda: conda-forge::scanpy +tags: + - single-cell + - preprocessing + - clustering + - visualization + - differential expression +license: BSD-3-Clause +version: 1.11.5 +contact: + - flying-sheep + - ilan-gold +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/schist/meta.yaml b/packages/schist/meta.yaml new file mode 100644 index 00000000..1f6a49eb --- /dev/null +++ b/packages/schist/meta.yaml @@ -0,0 +1,20 @@ +name: schist +description: schist applies Stochastic Block Models (SBM) to the analysis of single cell data, in particular to identify cell populations +project_home: https://github.com/dawe/schist +documentation_home: https://schist.readthedocs.io +tutorials_home: https://schist.readthedocs.io/en/latest/tutorials.html +install: + conda: conda-forge::schist +license: BSD-3-Clause +tags: + - clustering + - single-cell +publications: + - 10.1186/s12859-021-04489-7 +version: v0.8.1 +contact: + - dawe + - leomorelli +test_command: | + pytest conftest.py +category: ecosystem diff --git a/packages/scib/meta.yaml b/packages/scib/meta.yaml new file mode 100644 index 00000000..a470e0c5 --- /dev/null +++ b/packages/scib/meta.yaml @@ -0,0 +1,22 @@ +name: scib +description: | + Evaluating single-cell data integration methods +project_home: https://github.com/theislab/scib +documentation_home: https://scib.readthedocs.io +publications: + - 10.1038/s41592-021-01336-8 +install: + pypi: scib +tags: + - benchmarking + - single cell + - data integration +license: MIT +version: v1.0.5 +contact: + - mumichae + - LuckyMD + - danielStrobl + - mbuttner +test_command: pip install ".[test,rpy2,harmony,scvi,scanorama]" && pytest +category: ecosystem diff --git a/packages/scirpy/logo.svg b/packages/scirpy/logo.svg new file mode 100644 index 00000000..e24754f8 --- /dev/null +++ b/packages/scirpy/logo.svg @@ -0,0 +1 @@ + diff --git a/packages/scirpy/meta.yaml b/packages/scirpy/meta.yaml new file mode 100644 index 00000000..a12d5396 --- /dev/null +++ b/packages/scirpy/meta.yaml @@ -0,0 +1,25 @@ +name: Scirpy +description: | + Scirpy is a scalable toolkit to analyse T-cell receptor or B-cell receptor repertoires + from single-cell RNA sequencing data. It seamlessly integrates with scanpy and provides + various modules for data import, analysis and visualization. +project_home: https://github.com/scverse/scirpy +documentation_home: https://scirpy.scverse.org/ +tutorials_home: https://scirpy.scverse.org/en/latest/tutorials.html +publications: + - 10.1093/bioinformatics/btaa611 +install: + pypi: scirpy + conda: bioconda::scirpy +tags: + - immune receptor + - TCR + - BCR + - AIRR +license: BSD-3-Clause +version: 0.22.3 +contact: + - grst +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/scmcp/meta.yaml b/packages/scmcp/meta.yaml new file mode 100644 index 00000000..a4e5dfdc --- /dev/null +++ b/packages/scmcp/meta.yaml @@ -0,0 +1,17 @@ +name: scmcp +description: A MCP server hub for scRNA-Seq analysis software. +project_home: https://github.com/scmcphub +documentation_home: https://docs.scmcphub.org +install: + pypi: scmcp +tags: + - scRNA-seq + - bioinformatics + - LLM + - AI +license: BSD-3-Clause +version: v0.2.2 +contact: + - huangsh +test_command: uv run --no-sync pytest +category: ecosystem diff --git a/packages/sctriangulate/meta.yaml b/packages/sctriangulate/meta.yaml new file mode 100644 index 00000000..4ded158e --- /dev/null +++ b/packages/sctriangulate/meta.yaml @@ -0,0 +1,18 @@ +name: scTriangulate +description: | + Python package to mix-and-match conflicting clustering results in single cell analysis and generate reconciled clustering solutions +project_home: https://github.com/frankligy/scTriangulate +documentation_home: https://sctriangulate.readthedocs.io/en/latest/get_started.html +tutorials_home: https://sctriangulate.readthedocs.io/en/latest/tutorial.html +publications: + - 10.1101/2021.10.16.464640 +install: + pypi: sctriangulate +tags: + - clustering +license: MIT +version: v0.12.0 +contact: + - frankligy +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/scvelo/meta.yaml b/packages/scvelo/meta.yaml new file mode 100644 index 00000000..a359f1d2 --- /dev/null +++ b/packages/scvelo/meta.yaml @@ -0,0 +1,18 @@ +name: scVelo +description: | + scVelo is a scalable toolkit for RNA velocity analysis in single cells, based on [Bergen et al., Nature Biotech, 2020](https://doi.org/10.1038/s41587-020-0591-3). +project_home: https://github.com/theislab/scvelo +documentation_home: https://scvelo.readthedocs.io +publications: + - 10.1038/s41587-020-0591-3 +install: + pypi: scvelo +tags: + - rna velocity +license: BSD-3-Clause +version: v0.2.5 +contact: + - WeilerP + - VolkerBergen +test_command: pip install -e '.[dev]' && pytest +category: ecosystem diff --git a/packages/scverse-tutorials/meta.yaml b/packages/scverse-tutorials/meta.yaml new file mode 100644 index 00000000..509c448f --- /dev/null +++ b/packages/scverse-tutorials/meta.yaml @@ -0,0 +1,15 @@ +name: scverse-tutorials +description: | + Tutorials and tutorials registry for scverse.org/learn. +project_home: https://github.com/scverse/scverse-tutorials +documentation_home: https://scverse-tutorials.readthedocs.io/en/latest/ +tutorials_home: https://scverse-tutorials.readthedocs.io/en/latest/ +tags: + - tutorials + - education + - documentation +license: BSD-3-Clause +contact: + - grst + - flying-sheep +category: core-infrastructure diff --git a/packages/scverse.github.io/meta.yaml b/packages/scverse.github.io/meta.yaml new file mode 100644 index 00000000..82bfc433 --- /dev/null +++ b/packages/scverse.github.io/meta.yaml @@ -0,0 +1,12 @@ +name: scverse.github.io +description: | + scverse.org website +project_home: https://github.com/scverse/scverse.github.io +documentation_home: https://scverse.org +tags: + - website + - documentation +license: BSD-3-Clause +authors: + - gtca +category: core-infrastructure diff --git a/packages/scvi-tools/logo.svg b/packages/scvi-tools/logo.svg new file mode 100755 index 00000000..0ecc23a5 --- /dev/null +++ b/packages/scvi-tools/logo.svg @@ -0,0 +1 @@ + diff --git a/packages/scvi-tools/meta.yaml b/packages/scvi-tools/meta.yaml new file mode 100644 index 00000000..56c55d56 --- /dev/null +++ b/packages/scvi-tools/meta.yaml @@ -0,0 +1,44 @@ +name: scvi-tools +description: | + scvi-tools is a library for developing and deploying machine learning models based on + PyTorch and AnnData. With an emphasis on probabilistic models, scvi-tools streamlines + the development process via training, data management, and user interface abstractions. + scvi-tools also contains easy-to-use implementations of more than 14 state-of-the-art + probabilistic models in the field. +project_home: https://github.com/scverse/scvi-tools +documentation_home: https://docs.scvi-tools.org/en/stable/ +tutorials_home: https://docs.scvi-tools.org/en/stable/tutorials/index.html +publications: + - 10.1038/s41587-021-01206-w # Scvi-tools library paper, NBT 2022 + - 10.1038/s41587-022-01272-8 # DestVI + - 10.1038/s41592-020-01050-x # totalVI + - 10.15252/msb.20209620 # scANVI + - 10.48550/arXiv.1905.02269 # gimVI + - 10.1101/794289 # scvi-tools DE analysis + - 10.1093/bioinformatics/btaa169 # Interpretable factor models, Bioinformatics 2020 + - 10.1101/794875 # AutoZI + - 10.1038/s41592-018-0229-2 # scVI + - 10.1038/s41592-023-01909-9 # multiVI + - 10.1016/j.crmeth.2022.100182 # peakVI + - 10.1038/s41592-025-02808-x # MrVI + - 10.1038/s41592-025-02799-9 # scVI hub + - 10.1101/2025.01.20.634005 # resolVI + - 10.1038/s41592-023-01994-w # VeloVI + - 10.1101/2025.09.07.674699 # CytoVI + - 10.1101/2025.06.01.657182 # ScVIVA +install: + pypi: scvi-tools + conda: conda-forge::scvi-tools +tags: + - machine learning + - probabilistic models + - variational inference + - deep learning +license: BSD-3-Clause +version: 1.4.0.post1 +contact: + - ori-kron-wis + - canergen +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/scxmatch/meta.yaml b/packages/scxmatch/meta.yaml new file mode 100644 index 00000000..c599ad2b --- /dev/null +++ b/packages/scxmatch/meta.yaml @@ -0,0 +1,27 @@ +name: scxmatch +description: | + Single-cell Cross Match (scxmatch) is a is a Python package that implements Rosenbaum's cross-match test using distance-based matching to assess distribution shifts between two groups of high-dimensional data. + This is particularly useful in analyzing multivariate distributions in structured data, such as single-cell RNA-seq or ATAC-seq. +project_home: https://github.com/bionetslab/scxmatch +documentation_home: https://github.com/bionetslab/scxmatch +tutorials_home: https://github.com/bionetslab/scxmatch +publications: + - 10.1101/2025.06.25.661473 +install: + conda: bioconda::scxmatch +tags: + - scRNA-seq + - single-cell + - python + - statistical testing + - distance-based matching + - perturbation + - condition +license: MIT +version: v0.1.0 +contact: + - annmoel + - dbblumenthal +test_command: | + conda install scxmatch -c conda-forge -c bioconda && git clone https://github.com/bionetslab/scxmatch.git && cd scxmatch/tests/ && python test_mwe.py +category: ecosystem diff --git a/packages/scyan/meta.yaml b/packages/scyan/meta.yaml new file mode 100644 index 00000000..1abe9a4c --- /dev/null +++ b/packages/scyan/meta.yaml @@ -0,0 +1,23 @@ +name: scyan +description: | + Biology-driven deep generative model for cell-type annotation in cytometry. + Scyan is an interpretable model that also corrects batch-effect and + can be used for debarcoding or population discovery. +project_home: https://github.com/MICS-Lab/scyan +documentation_home: https://mics-lab.github.io/scyan/ +tutorials_home: https://mics-lab.github.io/scyan/tutorials/usage/ +publications: + - 10.1093/bib/bbad260 +install: + pypi: scyan +tags: + - cytometry + - annotation + - batch-effect correction + - debarcoding +license: BSD-3-Clause +version: v1.5.0 +contact: + - quentinblampey +test_command: pip install ".[dev]" && pytest +category: ecosystem diff --git a/packages/sift-sc/meta.yaml b/packages/sift-sc/meta.yaml new file mode 100644 index 00000000..77af9977 --- /dev/null +++ b/packages/sift-sc/meta.yaml @@ -0,0 +1,20 @@ +name: sift-sc +description: | + SiFT is a computational framework which aims to uncover the underlying structure by filtering out previously exposed biological signals. + SiFT can be applied to a wide range of tasks, from (i) the removal of unwanted variation as a pre-processing step, through (ii) revealing hidden biological structure by utilizing prior knowledge with respect to existing signal, to (iii) uncovering trajectories of interest using reference data to remove unwanted variation. +project_home: https://github.com/nitzanlab/sift-sc +documentation_home: https://sift-sc.readthedocs.io +tutorials_home: https://sift-sc.readthedocs.io +install: + pypi: sift-sc +tags: + - single-cell + - signals + - filter +license: BSD-3-Clause +version: v0.1.0 +contact: + - zoepiran +test_command: | + pip install ".[test]" && pytest +category: ecosystem diff --git a/packages/sincei/meta.yaml b/packages/sincei/meta.yaml new file mode 100644 index 00000000..79fa5e21 --- /dev/null +++ b/packages/sincei/meta.yaml @@ -0,0 +1,33 @@ +name: sincei +description: | + sincei provides a flexible, easy-to-use command-line interface and python API to work with single-cell epigenomics data directly from BAM files. It can: + - Aggregate signal in bins, genes or any feature of interest from single-cells. + - Perform read-level and count-level quality control. + - Perform dimensionality reduction and clustering of various types of single-cell data (open chromatin, histone marks, methylation etc..). + - Create coverage files (bigwigs) for visualization. +project_home: https://github.com/bhardwaj-lab/sincei +documentation_home: https://sincei.readthedocs.io/en/latest/ +publications: + - 10.1101/2024.07.27.605424 +install: + pypi: sincei +tags: + - single-cell + - preprocessing + - quality control + - clustering + - visualization + - epigenomics + - multi omics + - BAM +license: MIT +version: v0.5.1 +authors: + - vivekbhr + - saroudant +contact: + - vivekbhr + - fsanchogomez +category: ecosystem +test_command: | + pip install ."[dev]" && pytest diff --git a/packages/sobolev-alignment/meta.yaml b/packages/sobolev-alignment/meta.yaml new file mode 100644 index 00000000..83055ce1 --- /dev/null +++ b/packages/sobolev-alignment/meta.yaml @@ -0,0 +1,23 @@ +name: Sobolev Alignment +description: | + Sobolev alignment of deep probabilistic models for comparing single cell profiles from pre-clinical models and patients +project_home: https://github.com/NKI-CCB/sobolev_alignment +documentation_home: https://sobolev-alignment.readthedocs.io/ +publications: + - 10.1101/2022.03.08.483431 +install: + pypi: sobolev-alignment +tags: + - ML + - deep-generative-models + - kernel-methods + - pre-clinical + - clinical + - scrnaseq +license: MIT +version: 1.0.0 +contact: + - saroudant +test_command: | + pip install ."[dev]" && pytest +category: ecosystem diff --git a/packages/sopa/meta.yaml b/packages/sopa/meta.yaml new file mode 100644 index 00000000..364a8f0d --- /dev/null +++ b/packages/sopa/meta.yaml @@ -0,0 +1,23 @@ +name: sopa +description: | + Technology-invariant pipeline for spatial-omics analysis that + scales to millions of cells. It includes segmentation, annotation, + spatial statistics, and efficient visualization. +project_home: https://github.com/gustaveroussy/sopa +documentation_home: https://gustaveroussy.github.io/sopa/ +publications: + - 10.1038/s41467-024-48981-z +install: + pypi: sopa +tags: + - spatial-omics + - spatial-transcriptomics + - multiplex imaging + - spatialdata + - pipeline +license: BSD-3-Clause +version: v1.0.0 +contact: + - quentinblampey +test_command: pip install ".[dev,cellpose]" && pytest +category: ecosystem diff --git a/packages/spatial-eggplant/meta.yaml b/packages/spatial-eggplant/meta.yaml new file mode 100644 index 00000000..d09db477 --- /dev/null +++ b/packages/spatial-eggplant/meta.yaml @@ -0,0 +1,19 @@ +name: spatial-eggplant +description: | + Python package designed to transfer information from multiple spatial-transcriptomics data sets to a single reference representing a Common Coordinate Framework (CCF). +project_home: https://github.com/almaan/eggplant +documentation_home: https://spatial-eggplant.readthedocs.io/en/latest/index.html +tutorials_home: https://spatial-eggplant.readthedocs.io/en/latest/index.html +publications: + - 10.1101/2021.11.11.468178 +install: + pypi: spatial-eggplant +tags: + - spatial alignment + - spatial registration +license: MIT +version: v0.2.3 +contact: + - almaan +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/spatialdata/logo.svg b/packages/spatialdata/logo.svg new file mode 100644 index 00000000..728efc57 --- /dev/null +++ b/packages/spatialdata/logo.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/spatialdata/meta.yaml b/packages/spatialdata/meta.yaml new file mode 100644 index 00000000..95d0b825 --- /dev/null +++ b/packages/spatialdata/meta.yaml @@ -0,0 +1,23 @@ +name: SpatialData +description: | + SpatialData is a data framework that comprises a FAIR storage format and a collection of + python libraries for performant access, alignment, and processing of uni- and multi-modal + spatial omics datasets. +project_home: https://github.com/scverse/spatialdata +documentation_home: https://spatialdata.scverse.org/en/latest/ +tutorials_home: https://spatialdata.scverse.org/en/latest/tutorials/notebooks/notebooks.html +publications: + - 10.1038/s41592-024-02212-x +install: + pypi: spatialdata +tags: + - data structure + - spatial omics + - FAIR +license: BSD-3-Clause +version: 0.5.0 +contact: + - LucaMarconato + - melonora +logo: logo.svg +category: core-datastructure diff --git a/packages/spatialproteomics/meta.yaml b/packages/spatialproteomics/meta.yaml new file mode 100644 index 00000000..855ca35b --- /dev/null +++ b/packages/spatialproteomics/meta.yaml @@ -0,0 +1,23 @@ +name: spatialproteomics +description: | + Spatialproteomics is an interoperable toolbox for analyzing highly multiplexed fluorescence image data. + This analysis involves a sequence of steps, including segmentation, image processing, + marker quantification, cell type classification, and neighborhood analysis. +project_home: https://github.com/sagar87/spatialproteomics +documentation_home: https://sagar87.github.io/spatialproteomics +tutorials_home: https://sagar87.github.io/spatialproteomics/notebooks/ExampleWorkflow.html +install: + pypi: spatialproteomics +tags: + - spatial-omics + - spatial-proteomics + - multiplex imaging + - spatialdata + - pipeline +license: MIT +version: v0.7.0 +contact: + - MeyerBender + - sagar87 +test_command: pip install ".[all,dev]" && pytest +category: ecosystem diff --git a/packages/spatiomic/meta.yaml b/packages/spatiomic/meta.yaml new file mode 100644 index 00000000..809938b2 --- /dev/null +++ b/packages/spatiomic/meta.yaml @@ -0,0 +1,21 @@ +name: spatiomic +description: | + spatiomic is a computational library for the analysis of spatial proteomics, mainly via pixel-based clustering, differential cluster abundance analysis and spatial statistics. +project_home: https://github.com/complextissue/spatiomic +documentation_home: https://spatiomic.org +tutorials_home: https://spatiomic.org/latest/tutorials/full_example.html +install: + pypi: spatiomic +tags: + - spatial biology + - spatial proteomics + - spatial omics + - multiplexed protein imaging + - PathoPlex + - subcellular analysis +license: GPL-3.0-only +version: v0.5.0 +contact: + - maltekuehl +test_command: uv run pytest -m "not gpu" +category: ecosystem diff --git a/packages/squidpy/logo.svg b/packages/squidpy/logo.svg new file mode 100644 index 00000000..3b74b650 --- /dev/null +++ b/packages/squidpy/logo.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/squidpy/meta.yaml b/packages/squidpy/meta.yaml new file mode 100644 index 00000000..fae640b3 --- /dev/null +++ b/packages/squidpy/meta.yaml @@ -0,0 +1,26 @@ +name: Squidpy +description: | + Squidpy is a tool for the analysis and visualization of spatial molecular data. It builds + on top of scanpy and anndata, from which it inherits modularity and scalability. It provides + analysis tools that leverages the spatial coordinates of the data, as well as tissue images + if available. +project_home: https://github.com/scverse/squidpy +documentation_home: https://squidpy.readthedocs.io/ +tutorials_home: https://squidpy.readthedocs.io/en/latest/notebooks/tutorials/index.html +publications: + - 10.1038/s41592-021-01358-2 +install: + pypi: squidpy + conda: conda-forge::squidpy +tags: + - spatial omics + - spatial transcriptomics + - image analysis +license: BSD-3-Clause +version: 1.6.5 +contact: + - giovp + - timtreis +logo: logo.svg +test_command: pip install ".[test]" && pytest +category: core-framework diff --git a/packages/stats/meta.yaml b/packages/stats/meta.yaml new file mode 100644 index 00000000..61cd2eb8 --- /dev/null +++ b/packages/stats/meta.yaml @@ -0,0 +1,13 @@ +name: stats +description: | + Statistics for scverse +project_home: https://github.com/scverse/stats +documentation_home: https://scverse.org/stats/ +tags: + - statistics + - metrics +license: MIT +authors: + - maltekuehl + - grst +category: core-infrastructure diff --git a/packages/symphonypy/meta.yaml b/packages/symphonypy/meta.yaml new file mode 100644 index 00000000..9734db0b --- /dev/null +++ b/packages/symphonypy/meta.yaml @@ -0,0 +1,18 @@ +name: Symphonypy +description: | + Symphonypy is a pure Python port of Symphony label transfer algorithm for reference-based cell type + annotation. +project_home: https://github.com/potulabe/symphonypy +documentation_home: https://github.com/potulabe/symphonypy +install: + pypi: symphonypy +tags: + - label-transfer +license: GPL-3.0-only +version: v0.2.1 +contact: + - serjisa + - potulabe +test_command: | + pip install . && pytest +category: ecosystem diff --git a/packages/tangram/meta.yaml b/packages/tangram/meta.yaml new file mode 100644 index 00000000..4a01dc5f --- /dev/null +++ b/packages/tangram/meta.yaml @@ -0,0 +1,23 @@ +name: tangram +description: | + Spatial alignment and gene expression mapping of single cell transcriptomic data. +project_home: https://github.com/broadinstitute/Tangram +documentation_home: https://tangram-sc.readthedocs.io/en/latest/index.html +tutorials_home: https://tangram-sc.readthedocs.io/en/latest/tutorials.html +publications: + - 10.1038/s41592-021-01264-7 +install: + pypi: tangram-sc +tags: + - spatial decomposition + - spatial mapping +license: BSD-3-Clause +version: v1.0.3 +contact: + - ziqlu0722 + - lewlin + - gscalia + - gaddamshreya + - hejinhuang +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/vitessce/meta.yaml b/packages/vitessce/meta.yaml new file mode 100644 index 00000000..9d3573a0 --- /dev/null +++ b/packages/vitessce/meta.yaml @@ -0,0 +1,35 @@ +name: vitessce +description: | + Vitessce is an integrative visualization framework for multimodal and 2D/3D spatially resolved single-cell data. It consists of reusable, interactive linked views including scatterplot embedding views, + 2D/3D spatial image views, genome browser tracks, statistical plots, and control views, built on web technologies such as WebGL and WebXR. +project_home: https://github.com/vitessce/vitessce +documentation_home: https://vitessce.github.io/vitessce-python/ +tutorials_home: https://github.com/vitessce/vitessce/tree/main/examples +publications: + - 10.1038/s41592-024-02436-x +install: + pypi: vitessce +tags: + - imaging +license: MIT +version: v3.5.7 +contact: + - keller-mark + - mccalluc + - ilan-gold + - thomaslchan + - manzt + - john-conroy + - ngehlenborg + - jkmarx + - sehilyi + - rj3d + - alexvpickering + - cosa65 + - dannda + - alexkb0009 + - ivirshup + - romanhaa + - will-moore +test_command: pip install "." && pytest +category: ecosystem diff --git a/packages/wsidata/meta.yaml b/packages/wsidata/meta.yaml new file mode 100644 index 00000000..cdddab0b --- /dev/null +++ b/packages/wsidata/meta.yaml @@ -0,0 +1,18 @@ +name: wsidata +description: | + wsidata is a data-structure for efficient IO of Whole Slide Images based on spatialdata. +project_home: https://github.com/rendeirolab/wsidata +documentation_home: https://wsidata.readthedocs.io/en/latest/ +install: + pypi: wsidata +tags: + - Pathology + - Whole Slide Imaging +license: MIT +version: v0.3.0 +contact: + - Mr-Milk + - eabila + - afrendeiro +test_command: uv run task test +category: ecosystem diff --git a/packages/zellkonverter/logo.svg b/packages/zellkonverter/logo.svg new file mode 100644 index 00000000..482b3e90 --- /dev/null +++ b/packages/zellkonverter/logo.svg @@ -0,0 +1,358 @@ + +image/svg+xmlPywww.bioconductor.orgwww.bioconductor.orgzellkonverterR diff --git a/packages/zellkonverter/meta.yaml b/packages/zellkonverter/meta.yaml new file mode 100644 index 00000000..653082e5 --- /dev/null +++ b/packages/zellkonverter/meta.yaml @@ -0,0 +1,21 @@ +name: zellkonverter +description: | + An Bioconductor R package that enables reading and writing of H5AD files + and conversion between AnnData and SingleCellExperiment objects by wrapping + the Python anndata package. +project_home: https://github.com/theislab/zellkonverter +documentation_home: https://bioconductor.org/packages/zellkonverter/ +tutorials_home: https://theislab.github.io/zellkonverter/ +install: + bioconductor: zellkonverter +license: MIT +tags: + - data structures + - interoperability + - R + - Bioconductor +version: 1.20.0 +contact: + - lazappi +logo: logo.svg +category: ecosystem diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 00000000..9694f19c --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,6 @@ +# Scripts + +To hack on the scripts, `cd` to this directory, then + +- Use `prek/pre-commit run -a jsonschema-gentypes` to generate types from schema initially +- Use `prek/pre-commit install` to so checks are automatically run on commit diff --git a/scripts/pyproject.toml b/scripts/pyproject.toml new file mode 100644 index 00000000..fd3b5f04 --- /dev/null +++ b/scripts/pyproject.toml @@ -0,0 +1,80 @@ +[build-system] +build-backend = "hatchling.build" + +requires = [ "hatch-vcs", "hatchling" ] + +[project] +name = "ecosystem-scripts" +description = "scripts for ecosystem package data" +readme = "../README.md" +license = "GPL-3.0" +authors = [ + { name = "Philipp A.", email = "flying-sheep@web.de" }, + { name = "Gregor Sturm", email = "gregor.sturm@scverse.org" }, +] +requires-python = ">=3.12" +classifiers = [ + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", +] +dynamic = [ "version" ] +dependencies = [ + "httpx", + "httpx-retries", + "jsonschema>=4.25.1", + "pillow>=12", + "pygithub", + "pyyaml", + "rich", +] + +urls.Documentation = "https://github.com/scverse/ecosystem-packages#readme" +urls.Issues = "https://github.com/scverse/ecosystem-packages/issues" +urls.Source = "https://github.com/scverse/ecosystem-packages" +scripts.register-template-repos = "ecosystem_scripts.template_repo_registry:main" +scripts.validate-registry = "ecosystem_scripts.validate_registry:main" + +[tool.hatch.version] +source = "vcs" +fallback-version = "0.0" + +[tool.hatch.envs.default] +python = "3.13" + +[tool.ruff] +line-length = 120 +lint.select = [ + "A", + "ARG", + "B", + "C", + "DTZ", + "E", + "EM", + "F", + "FBT", + "I", + "ICN", + "ISC", + "N", + "PLC", + "PLE", + "PLR", + "PLW", + "RUF", + "S", + "T", + "TC", + "TID", + "UP", + "W", + "YTT", +] +lint.ignore = [ ] + +[tool.mypy] +strict = true +explicit_package_bases = true +mypy_path = [ "$MYPY_CONFIG_FILE_DIR/typings", "$MYPY_CONFIG_FILE_DIR/src" ] diff --git a/scripts/src/ecosystem_scripts/__init__.py b/scripts/src/ecosystem_scripts/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/scripts/src/ecosystem_scripts/_logging.py b/scripts/src/ecosystem_scripts/_logging.py new file mode 100644 index 00000000..1708184b --- /dev/null +++ b/scripts/src/ecosystem_scripts/_logging.py @@ -0,0 +1,13 @@ +from logging import basicConfig, getLogger + +from rich.logging import RichHandler + +log = getLogger(__name__) + + +def setup_logging() -> None: + """Set up logging and rich traceback.""" + basicConfig(level="INFO", handlers=[RichHandler()]) + + # Suppress httpx INFO logs to reduce verbosity + getLogger("httpx").setLevel("WARNING") diff --git a/scripts/src/ecosystem_scripts/schema.json b/scripts/src/ecosystem_scripts/schema.json new file mode 100644 index 00000000..d753063b --- /dev/null +++ b/scripts/src/ecosystem_scripts/schema.json @@ -0,0 +1,261 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://raw.githubusercontent.com/scverse/ecosystem-packages/main/scripts/src/ecosystem_scripts/schema.json", + "version": "2.0", + "title": "Scverse Ecosystem Packages", + "description": "An approved scverse ecosystem package that fulfils some minimal requirements", + "type": "object", + "properties": { + "name": { + "description": "The name of the package. Must be unique", + "type": "string" + }, + "description": { + "description": "Summary of the purpose of the package (1-2 sentences).", + "type": "string" + }, + "project_home": { + "description": "Link to the source code of the project (Usually a GitHub project page)", + "type": "string", + "format": "uri" + }, + "documentation_home": { + "descripton": "Link to the documentation of the package (e.g. readthedocs)", + "type": "string", + "format": "uri" + }, + "tutorials_home": { + "descripton": "Link to the tutorials/vignette (often a subpage of the documentation)", + "type": "string", + "format": "uri" + }, + "install": { + "type": "object", + "properties": { + "pypi": { + "description": "PyPI identifier", + "type": "string" + }, + "conda": { + "description": "Conda identifier, including channel (e.g. conda-forge::scanpy)", + "type": "string", + "pattern": "(.*)::(.*)" + }, + "cran": { + "description": "CRAN identifier", + "type": "string" + }, + "bioconductor": { + "description": "Bioconductor identifier", + "type": "string" + } + }, + "minProperties": 1 + }, + "license": { + "description": "The license of the code. Must be a OSI-approved SPDX license identifier (see https://spdx.org/licenses/)", + "comment": "import pandas as pd; from json import dumps; dumps(pd.read_html('https://spdx.org/licenses/')[0].loc[lambda x: x['OSI Approved?'] == 'Y']['Identifier'].tolist())", + "type": "string", + "enum": [ + "0BSD", + "AAL", + "AFL-1.1", + "AFL-1.2", + "AFL-2.0", + "AFL-2.1", + "AFL-3.0", + "AGPL-3.0-only", + "AGPL-3.0-or-later", + "Apache-1.1", + "Apache-2.0", + "APL-1.0", + "APSL-1.0", + "APSL-1.1", + "APSL-1.2", + "APSL-2.0", + "Artistic-1.0", + "Artistic-1.0-cl8", + "Artistic-1.0-Perl", + "Artistic-2.0", + "BSD-1-Clause", + "BSD-2-Clause", + "BSD-2-Clause-Patent", + "BSD-3-Clause", + "BSD-3-Clause-LBNL", + "BSL-1.0", + "CAL-1.0", + "CAL-1.0-Combined-Work-Exception", + "CATOSL-1.1", + "CDDL-1.0", + "CECILL-2.1", + "CERN-OHL-P-2.0", + "CERN-OHL-S-2.0", + "CERN-OHL-W-2.0", + "CNRI-Python", + "CPAL-1.0", + "CPL-1.0", + "CUA-OPL-1.0", + "ECL-1.0", + "ECL-2.0", + "EFL-1.0", + "EFL-2.0", + "Entessa", + "EPL-1.0", + "EPL-2.0", + "EUDatagrid", + "EUPL-1.1", + "EUPL-1.2", + "Fair", + "Frameworx-1.0", + "GPL-2.0-only", + "GPL-2.0-or-later", + "GPL-3.0-only", + "GPL-3.0-or-later", + "HPND", + "Intel", + "IPA", + "IPL-1.0", + "ISC", + "Jam", + "LGPL-2.0-only", + "LGPL-2.0-or-later", + "LGPL-2.1-only", + "LGPL-2.1-or-later", + "LGPL-3.0-only", + "LGPL-3.0-or-later", + "LiLiQ-P-1.1", + "LiLiQ-R-1.1", + "LiLiQ-Rplus-1.1", + "LPL-1.0", + "LPL-1.02", + "LPPL-1.3c", + "MirOS", + "MIT", + "MIT-0", + "MIT-Modern-Variant", + "Motosoto", + "MPL-1.0", + "MPL-1.1", + "MPL-2.0", + "MPL-2.0-no-copyleft-exception", + "MS-PL", + "MS-RL", + "MulanPSL-2.0", + "Multics", + "NASA-1.3", + "Naumen", + "NCSA", + "NGPL", + "Nokia", + "NPOSL-3.0", + "NTP", + "OCLC-2.0", + "OFL-1.1", + "OFL-1.1-no-RFN", + "OFL-1.1-RFN", + "OGTSL", + "OLDAP-2.8", + "OSET-PL-2.1", + "OSL-1.0", + "OSL-2.0", + "OSL-2.1", + "OSL-3.0", + "PHP-3.0", + "PHP-3.01", + "PostgreSQL", + "Python-2.0", + "QPL-1.0", + "RPL-1.1", + "RPL-1.5", + "RPSL-1.0", + "RSCPL", + "SimPL-2.0", + "SISSL", + "Sleepycat", + "SPL-1.0", + "UCL-1.0", + "Unicode-DFS-2016", + "Unlicense", + "UPL-1.0", + "VSL-1.0", + "W3C", + "Watcom-1.0", + "Xnet", + "Zlib", + "ZPL-2.0", + "ZPL-2.1" + ] + }, + "tags": { + "description": "Keywords that describe the package", + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + }, + "publications": { + "description": "DOIs of publications describing the package", + "type": "array", + "items": { + "type": "string", + "comment": "DOI regex from https://www.crossref.org/blog/dois-and-matching-regular-expressions/", + "pattern": "^10.\\d{4,9}\\/[-._;()\\/:A-Za-z0-9]+$" + } + }, + "version": { + "description": "The version of the package at the point when this entry was created or updated", + "type": "string" + }, + "contact": { + "description": "Point of contact for this package. Does not need to be the full list of maintainers. Entries must be Github user IDs.", + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + }, + "logo": { + "description": "Path to the logo (relative to meta.yaml). Should be either logo.png, logo.webp, or logo.svg. In case of a PNG image, it must fit in a bounding box of 512x512px and one dimension must be exactly 512px.", + "type": "string", + "pattern": "logo\\.(svg|png|webp)" + }, + "test_command": { + "description": "A shell command to install the package and execute the tests, assuming you are inside a freshly cloned copy of the package repository. Often this will be `pip install \".[test]\" && pytest`", + "type": ["string"] + }, + "category": { + "type": "string", + "enum": [ + "core-framework", + "core-datastructure", + "core-infrastructure", + "ecosystem" + ], + "description": "Package category for the website and statistics." + } + }, + "required": [ + "name", + "description", + "project_home", + "documentation_home", + "license", + "tags", + "category" + ], + "if": { + "not": { + "properties": { + "category": { + "const": "core-infrastructure" + } + } + } + }, + "then": { + "required": ["install", "version"] + } +} diff --git a/scripts/src/ecosystem_scripts/template_repo_registry.py b/scripts/src/ecosystem_scripts/template_repo_registry.py new file mode 100644 index 00000000..892b3847 --- /dev/null +++ b/scripts/src/ecosystem_scripts/template_repo_registry.py @@ -0,0 +1,140 @@ +"""Maintenance script for updating list of repositories that use the +scverse template in template-repos.yml. + +After installing this via `pip install ./scripts` from the repo root, +It is available as `register-template-repos`. + +Call `register-template-repos template-repos.yml` to update the file. +Each entry marked with `skip: true` will not be served PRs. +""" + +from __future__ import annotations + +import os +import sys +from pathlib import Path +from typing import TYPE_CHECKING, NotRequired, TypedDict, cast + +from github import Github, GithubException, UnknownObjectException +from yaml import safe_dump, safe_load + +from ._logging import log, setup_logging + +if TYPE_CHECKING: + from collections.abc import Iterable, Sequence + + +class Repo(TypedDict): + url: str + skip: NotRequired[bool] + + +def parse_repos(path: Path) -> list[Repo]: + if not path.is_file(): + log.info(f"No existing file found at: {path}") + return [] + with path.open() as f: + repos = cast("list[Repo]", safe_load(f)) + log.info(f"Found {len(repos)} known repos in: {path}") + return repos + + +def search_repos(github_token: str | None) -> set[str]: + g = Github(github_token) + files = g.search_code('filename:.cruft.json "https://github.com/scverse/cookiecutter-scverse"') + repos = {file.repository for file in files} + return {r.html_url for r in repos} + + +def merge_repos(known: Iterable[Repo], new: Iterable[str]) -> list[Repo]: + repos = list(known) + n_known = len(repos) + known_urls = {repo["url"] for repo in repos} + for repo_url in new: + if repo_url not in known_urls: + repos.append(Repo(url=repo_url)) + log.info(f"Found {len(repos) - n_known} new repos in search") + return repos + + +def filter_repos(repos: list[Repo], github_token: str | None) -> list[Repo]: + """Filter repositories based on their GitHub status. + + Removes archived repositories, non-existent repositories, and repositories + that no longer have .cruft.json in their root. Updates URLs for moved repositories. + + Parameters + ---------- + repos + List of repositories to filter + github_token + GitHub API token for authentication + + Returns + ------- + Filtered list of repositories + """ + g = Github(github_token) + filtered_repos = [] + known_urls = {repo["url"] for repo in repos} + + for repo in repos: + url = repo["url"] + github_url_prefix = "https://github.com/" + if not url.startswith(github_url_prefix): + raise AssertionError + repo_name = url.replace(github_url_prefix, "") + log.info(f"Checking repo {repo_name}") + + try: + gh_repo = g.get_repo(repo_name) + except (GithubException, UnknownObjectException) as e: + # Repo doesn't exist or other error + log.info(f"Removing non-existent or inaccessible repo: {repo_name} ({e})") + continue + + # Check if repo is archived + if gh_repo.archived: + log.info(f"Removing archived repo: {repo_name}") + continue + + # Check if repo has been moved/renamed + if gh_repo.html_url != url: + log.info(f"Repo moved: {url} -> {gh_repo.html_url}") + if gh_repo.html_url in known_urls: + # duplicate already exists + continue + repo["url"] = gh_repo.html_url + + # Check if .cruft.json exists in root + try: + gh_repo.get_contents(".cruft.json") + except UnknownObjectException: + log.info(f"Removing repo without .cruft.json: {repo_name}") + continue + + filtered_repos.append(repo) + + return filtered_repos + + +def main(args: Sequence[str] | None = None) -> None: + setup_logging() + if args is None: + args = sys.argv[1:] + if len(args) != 1: + sys.exit("Usage: register-template-repos template-repos.yml") + path = Path(args[0]) + github_token = os.environ["GITHUB_TOKEN"] + repos = merge_repos( + parse_repos(path), + search_repos(github_token), + ) + repos = filter_repos(repos, github_token) + if repos: + with path.open("w") as f: + safe_dump(sorted(repos, key=lambda r: r["url"]), f, sort_keys=False) + + +if __name__ == "__main__": + main() diff --git a/scripts/src/ecosystem_scripts/validate_registry.py b/scripts/src/ecosystem_scripts/validate_registry.py new file mode 100644 index 00000000..53b678e7 --- /dev/null +++ b/scripts/src/ecosystem_scripts/validate_registry.py @@ -0,0 +1,433 @@ +#!/usr/bin/env python +"""Validate packages' meta.yaml and generate an output directory with json/images to be uploaded on Github Pages""" + +from __future__ import annotations + +import argparse +import json +import os +import shutil +import sys +from collections import defaultdict +from importlib.resources import files +from pathlib import Path +from textwrap import dedent +from typing import TYPE_CHECKING, cast + +import httpx +import jsonschema +import yaml +from httpx_retries import Retry, RetryTransport +from PIL import Image + +from ._logging import log, setup_logging + +if TYPE_CHECKING: + from collections.abc import Iterable, Mapping, Sequence + from importlib.resources.abc import Traversable + + from .schema import ScverseEcosystemPackages # pyright: ignore[reportMissingModuleSource] + + +# Constants +HERE = Path(__file__).parent +IMAGE_SIZE = 512 + + +class ValidationError(Exception): + pass + + +class ErrorList(list[Exception]): + """List of error messages. Ignores None objects, and logs an error when one gets added.""" + + def append(self, obj: Exception | None) -> None: + if obj is None: + return + log.error(f"Validation error: {obj}") + return super().append(obj) + + +class LinkChecker: + """Track known links and validate URLs.""" + + def __init__(self, client: httpx.Client) -> None: + self.known_links: set[str] = set() + self.client = client + + def check_and_register(self, url: str, context: str) -> None | ValidationError: + """Check if URL is duplicate, validate it exists, and register it. + + Parameters + ---------- + url + The URL to check and register + context + Context information for error messages (e.g., file being validated) + """ + if url in self.known_links: + msg = f"{context}: Duplicate link: {url}" + return ValidationError(msg) + + try: + response = self.client.head(url) + except Exception as e: + msg = f"URL {url} is not reachable: {e}" + return ValidationError(msg) + + if response.status_code != httpx.codes.OK: + msg = f"URL {url} is not reachable (error {response.status_code}). " + return ValidationError(msg) + + self.known_links.add(url) + return None + + +class GitHubUserValidator: + """Validate GitHub usernames using the GitHub API.""" + + def __init__(self, client: httpx.Client, github_token: str | None = None) -> None: + self.client = client + self.github_token = github_token + self.validated_users: set[str] = set() + + def validate_usernames(self, usernames: Sequence[str], context: str) -> None | ValidationError: + """Validate that a GitHub username exists. + + Parameters + ---------- + username + The GitHub username to validate + context + Context information for error messages (e.g., file being validated) + """ + + if not (unvalidated := list(set(usernames) - self.validated_users)): + return None + + headers = {} + if self.github_token: + headers["Authorization"] = f"token {self.github_token}" + + q = "\n".join(f"user{i}: user(login: {json.dumps(name)}) {{ login }}" for i, name in enumerate(unvalidated)) + + try: + response = self.client.post( + "https://api.github.com/graphql", headers=headers, json={"query": f"query {{ {q} }}"} + ) + except Exception as e: + msg = f"{context}: Failed to validate GitHub users {unvalidated!r}: {e}" + return ValidationError(msg) + + if response.status_code != httpx.codes.OK: + msg = f"{context}: Failed to validate GitHub users {unvalidated!r} (error {response.status_code})" + return ValidationError(msg) + + gql_response = response.json() + if errors := gql_response.get("errors"): + error_msgs = "\n".join(f"- {error['message']}" for error in errors) + msg = f"{context}: Failed to validate GitHub users {unvalidated!r}:\n{error_msgs}" + return ValidationError(msg) + + self.validated_users |= set(unvalidated) + log.info(f"Validated GitHub users: {unvalidated!r}") + return None + + +class PyPIValidator: + """Validate PyPI package names against the PyPI API.""" + + def __init__(self, client: httpx.Client) -> None: + self.client = client + self.validated_packages: set[str] = set() + + def validate_package(self, package_name: str, context: str) -> None | ValidationError: + """Validate that a PyPI package exists. + + Parameters + ---------- + package_name + The PyPI package name to validate + context + Context information for error messages (e.g., file being validated) + """ + if package_name in self.validated_packages: + return None + + try: + response = self.client.head(f"https://pypi.org/pypi/{package_name}/json") + except Exception as e: + msg = f"{context}: Failed to validate PyPI package {package_name!r}: {e}" + return ValidationError(msg) + + if response.status_code == httpx.codes.NOT_FOUND: + msg = f"{context}: PyPI package {package_name!r} does not exist" + return ValidationError(msg) + if response.status_code != httpx.codes.OK: + msg = f"{context}: Failed to validate PyPI package {package_name!r} (error {response.status_code})" + return ValidationError(msg) + + self.validated_packages.add(package_name) + log.info(f"Validated PyPI package: {package_name}") + return None + + +class CondaValidator: + """Validate Conda package identifiers using the Anaconda API.""" + + def __init__(self, client: httpx.Client) -> None: + self.client = client + self.validated_packages: set[str] = set() + + def validate_package(self, package_spec: str, context: str) -> None | ValidationError: + """Validate that a Conda package exists. + + Parameters + ---------- + package_spec + The Conda package specification (e.g., "conda-forge::scanpy") + context + Context information for error messages (e.g., file being validated) + """ + if package_spec in self.validated_packages: + return None + + # Parse channel and package name + if "::" not in package_spec: + msg = f"{context}: Invalid Conda package spec {package_spec!r} (expected format: channel::package)" + return ValidationError(msg) + + channel, package_name = package_spec.split("::", 1) + + # Check package exists on the channel + try: + response = self.client.head(f"https://api.anaconda.org/package/{channel}/{package_name}") + except Exception as e: + msg = f"{context}: Failed to validate Conda package '{package_spec}': {e}" + return ValidationError(msg) + + if response.status_code == httpx.codes.NOT_FOUND: + msg = f"{context}: Conda package '{package_spec}' does not exist" + return ValidationError(msg) + if response.status_code != httpx.codes.OK: + msg = f"{context}: Failed to validate Conda package '{package_spec}' (error {response.status_code})" + return ValidationError(msg) + + self.validated_packages.add(package_spec) + log.info(f"Validated Conda package: {package_spec}") + return None + + +class CRANValidator: + """Validate CRAN package names using the CRAN API.""" + + def __init__(self, client: httpx.Client) -> None: + self.client = client + self.validated_packages: set[str] = set() + + def validate_package(self, package_name: str, context: str) -> None | ValidationError: + """Validate that a CRAN package exists. + + Parameters + ---------- + package_name + The CRAN package name to validate + context + Context information for error messages (e.g., file being validated) + """ + if package_name in self.validated_packages: + return None + + # CRAN packages can be checked via the packages database + try: + response = self.client.head(f"https://crandb.r-pkg.org/{package_name}") + except Exception as e: + msg = f"{context}: Failed to validate CRAN package '{package_name}': {e}" + return ValidationError(msg) + + if response.status_code == httpx.codes.NOT_FOUND: + msg = f"{context}: CRAN package '{package_name}' does not exist" + return ValidationError(msg) + if response.status_code != httpx.codes.OK: + msg = f"{context}: Failed to validate CRAN package '{package_name}' (error {response.status_code})" + return ValidationError(msg) + + self.validated_packages.add(package_name) + log.info(f"Validated CRAN package: {package_name}") + return None + + +def check_image(img_path: Path) -> None | ValidationError: + """Validates that the image exists and that it is either a SVG or fits into the 512x512 bounding box.""" + if not img_path.exists(): + msg = f"Image does not exist: {img_path}" + return ValidationError(msg) + if img_path.suffix == ".svg": + return None + with Image.open(img_path) as img: + width, height = img.size + if not ((width == IMAGE_SIZE and height <= IMAGE_SIZE) or (width <= IMAGE_SIZE and height == IMAGE_SIZE)): + msg = dedent( + f"""\ + When validating {img_path}: Image must fit in a {IMAGE_SIZE}x{IMAGE_SIZE}px bounding box + and one dimension must be exactly {IMAGE_SIZE} px. + Actual dimensions (width, height): ({width}, ({height}))." + """ + ) + return ValidationError(msg) + return None + + +def validate_packages( + schema_file: Traversable, registry_dir: Path, github_token: str | None = None +) -> tuple[Mapping[str, Sequence[Exception]], Sequence[ScverseEcosystemPackages]]: + """Find all package `meta.yaml` files in the registry dir and yield package records.""" + schema = json.loads(schema_file.read_bytes()) + + # Create HTTP client with retry configuration using httpx_retries transport + retry_transport = RetryTransport(retry=Retry(total=3, backoff_factor=2)) + retry_client = httpx.Client(follow_redirects=True, timeout=30.0, transport=retry_transport) + + # using different link checkers, + # because each of them may point to the same URL and this wouldn't qualify as duplicate + link_checker_home = LinkChecker(retry_client) + link_checker_docs = LinkChecker(retry_client) + link_checker_tutorials = LinkChecker(retry_client) + + github_validator = GitHubUserValidator(retry_client, github_token) + pypi_validator = PyPIValidator(retry_client) + conda_validator = CondaValidator(retry_client) + cran_validator = CRANValidator(retry_client) + + errors: defaultdict[str, ErrorList] = defaultdict(ErrorList) + package_metadata: list[ScverseEcosystemPackages] = [] + + for tmp_meta_file in sorted(registry_dir.rglob("meta.yaml"), key=lambda x: x.parent.name): + pkg_id = tmp_meta_file.parent.name + pkg_errors = errors[pkg_id] + log.info(f"Validating {pkg_id}") + with tmp_meta_file.open() as f: + tmp_meta = cast("ScverseEcosystemPackages", yaml.load(f, yaml.SafeLoader)) + + try: + jsonschema.validate(tmp_meta, schema) + except jsonschema.ValidationError as e: + pkg_errors.append(e) + + # Check and register all links + pkg_errors.append(link_checker_home.check_and_register(tmp_meta["project_home"], pkg_id)) + pkg_errors.append(link_checker_docs.check_and_register(tmp_meta["documentation_home"], pkg_id)) + if url := tmp_meta.get("tutorials_home"): + pkg_errors.append(link_checker_tutorials.check_and_register(url, pkg_id)) + + # Validate GitHub usernames in contact field + if usernames := tmp_meta.get("contact"): + pkg_errors.append(github_validator.validate_usernames(usernames, pkg_id)) + + # Validate install packages + if install_info := tmp_meta.get("install"): + if pypi_name := install_info.get("pypi"): + pkg_errors.append(pypi_validator.validate_package(pypi_name, pkg_id)) + if conda_name := install_info.get("conda"): + pkg_errors.append(conda_validator.validate_package(conda_name, pkg_id)) + if cran_name := install_info.get("cran"): + pkg_errors.append(cran_validator.validate_package(cran_name, pkg_id)) + + # Check logo (if available) and make path relative to root of registry + if "logo" in tmp_meta: + img_path = registry_dir / pkg_id / tmp_meta["logo"] + pkg_errors.append(check_image(img_path)) + tmp_meta["logo"] = str(img_path) + + package_metadata.append(tmp_meta) + + return errors, package_metadata + + +def make_output( + packages: Iterable[ScverseEcosystemPackages], + *, + outdir: Path | None = None, +) -> None: + """Create the output directory. + + If outdir is not set, don't copy anything, just print the JSON to stdout + + Structure: + outdir + - ecosystem.json # contains package metadata + - packagexxx/icon.svg # original icon filenames under a folder for each package. + - packageyyy/icon.png + """ + packages_rel: list[ScverseEcosystemPackages] = [] + for pkg in packages: + pkg_rel = pkg.copy() + if logo := pkg.get("logo"): + img_srcpath = Path(logo) + img_localpath = Path(img_srcpath.parent.name) / img_srcpath.name + pkg_rel["logo"] = str(img_localpath) + if outdir: + img_outpath = outdir / img_localpath + img_outpath.parent.mkdir() + shutil.copy(img_srcpath, img_outpath) + packages_rel.append(pkg_rel) + + if outdir: + with (outdir / "packages.json").open("w") as f: + json.dump(packages_rel, f) + else: + json.dump(packages_rel, sys.stdout, indent=2) + + +class Args(argparse.Namespace): + registry_dir: Path + outdir: Path | None + + +def main(args: Sequence[str] | None = None) -> None: + """Main entry point for the validate-registry command.""" + setup_logging() + if args is None: + args = sys.argv[1:] + + parser = argparse.ArgumentParser( + prog="validate-registry", + description=( + "Validate packages' meta.yaml and generate an output directory " + "with json/images to be uploaded on github pages." + ), + ) + parser.add_argument( + "--registry-dir", + type=Path, + # HERE is /scripts/src/ecosystem_scripts/, so go up 3 levels + default=HERE.parent.parent.parent / "packages", + help="Path to the registry directory containing package meta.yaml files", + ) + parser.add_argument("--outdir", type=Path, help="outdir that will contain the data to be uploaded on github pages") + + parsed_args = parser.parse_args(args, Args()) + if not parsed_args.registry_dir.is_dir(): + msg = f"Invalid Registry directory: {parsed_args.registry_dir}" + raise ValueError(msg) + + schema_file = files("ecosystem_scripts").joinpath("schema.json") + github_token = os.environ.get("GITHUB_TOKEN") + if parsed_args.outdir is not None: + parsed_args.outdir.mkdir(parents=True) + + log.info("Starting validation") + errors, packages = validate_packages(schema_file, parsed_args.registry_dir, github_token) + + if any(errors.values()): + log.error("Validation error occured in at least one package. Exiting.") + sys.exit(1) + else: + make_output(packages, outdir=parsed_args.outdir) + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + sys.exit(1) diff --git a/scripts/uv.lock b/scripts/uv.lock new file mode 100644 index 00000000..f0148fd9 --- /dev/null +++ b/scripts/uv.lock @@ -0,0 +1,690 @@ +version = 1 +revision = 3 +requires-python = ">=3.12" +resolution-markers = [ + "python_full_version >= '3.14' and platform_python_implementation != 'PyPy'", + "python_full_version < '3.14' and platform_python_implementation != 'PyPy'", + "platform_python_implementation == 'PyPy'", +] + +[[package]] +name = "anyio" +version = "4.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c6/78/7d432127c41b50bccba979505f272c16cbcadcc33645d5fa3a738110ae75/anyio-4.11.0.tar.gz", hash = "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4", size = 219094, upload-time = "2025-09-23T09:19:12.58Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/b3/9b1a8074496371342ec1e796a96f99c82c945a339cd81a8e73de28b4cf9e/anyio-4.11.0-py3-none-any.whl", hash = "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc", size = 109097, upload-time = "2025-09-23T09:19:10.601Z" }, +] + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "certifi" +version = "2025.10.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/5b/b6ce21586237c77ce67d01dc5507039d444b630dd76611bbca2d8e5dcd91/certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", size = 164519, upload-time = "2025-10-05T04:12:15.808Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", size = 163286, upload-time = "2025-10-05T04:12:14.03Z" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy' and platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "cryptography" +version = "46.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" }, + { url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" }, + { url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" }, + { url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" }, + { url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" }, + { url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" }, + { url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" }, + { url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" }, + { url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" }, + { url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" }, + { url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" }, + { url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" }, + { url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" }, + { url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" }, + { url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" }, + { url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" }, + { url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" }, + { url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" }, + { url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" }, + { url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" }, + { url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" }, + { url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" }, + { url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" }, + { url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" }, + { url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" }, + { url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" }, + { url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" }, + { url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" }, + { url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" }, + { url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" }, + { url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" }, + { url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" }, + { url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" }, + { url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" }, + { url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" }, +] + +[[package]] +name = "ecosystem-scripts" +source = { editable = "." } +dependencies = [ + { name = "httpx" }, + { name = "httpx-retries" }, + { name = "jsonschema" }, + { name = "pillow" }, + { name = "pygithub" }, + { name = "pyyaml" }, + { name = "rich" }, +] + +[package.metadata] +requires-dist = [ + { name = "httpx" }, + { name = "httpx-retries" }, + { name = "jsonschema", specifier = ">=4.25.1" }, + { name = "pillow", specifier = ">=12" }, + { name = "pygithub" }, + { name = "pyyaml" }, + { name = "rich" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "httpx-retries" +version = "0.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/40/b9b5e4c16fb86d2999840bb795b28670a61856c7f48f030530b412bf4133/httpx_retries-0.4.5.tar.gz", hash = "sha256:acee306d7384eefad71ac12fefe8b13d7b41c19595c538e68d9bd7e40e59539d", size = 13015, upload-time = "2025-10-17T15:55:23.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/0a/2626b5a2678f8072ba3174d3e40f81429fdc41d1cb993280dbc7ba3c4e3f/httpx_retries-0.4.5-py3-none-any.whl", hash = "sha256:ae22d6ef197a2da49242246a01d721474cbd6516b1fef155f6da694ee410bb37", size = 8301, upload-time = "2025-10-17T15:55:22.869Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "pillow" +version = "12.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/cace85a1b0c9775a9f8f5d5423c8261c858760e2466c79b2dd184638b056/pillow-12.0.0.tar.gz", hash = "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353", size = 47008828, upload-time = "2025-10-15T18:24:14.008Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/90/4fcce2c22caf044e660a198d740e7fbc14395619e3cb1abad12192c0826c/pillow-12.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:53561a4ddc36facb432fae7a9d8afbfaf94795414f5cdc5fc52f28c1dca90371", size = 5249377, upload-time = "2025-10-15T18:22:05.993Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e0/ed960067543d080691d47d6938ebccbf3976a931c9567ab2fbfab983a5dd/pillow-12.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71db6b4c1653045dacc1585c1b0d184004f0d7e694c7b34ac165ca70c0838082", size = 4650343, upload-time = "2025-10-15T18:22:07.718Z" }, + { url = "https://files.pythonhosted.org/packages/e7/a1/f81fdeddcb99c044bf7d6faa47e12850f13cee0849537a7d27eeab5534d4/pillow-12.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2fa5f0b6716fc88f11380b88b31fe591a06c6315e955c096c35715788b339e3f", size = 6232981, upload-time = "2025-10-15T18:22:09.287Z" }, + { url = "https://files.pythonhosted.org/packages/88/e1/9098d3ce341a8750b55b0e00c03f1630d6178f38ac191c81c97a3b047b44/pillow-12.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:82240051c6ca513c616f7f9da06e871f61bfd7805f566275841af15015b8f98d", size = 8041399, upload-time = "2025-10-15T18:22:10.872Z" }, + { url = "https://files.pythonhosted.org/packages/a7/62/a22e8d3b602ae8cc01446d0c57a54e982737f44b6f2e1e019a925143771d/pillow-12.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55f818bd74fe2f11d4d7cbc65880a843c4075e0ac7226bc1a23261dbea531953", size = 6347740, upload-time = "2025-10-15T18:22:12.769Z" }, + { url = "https://files.pythonhosted.org/packages/4f/87/424511bdcd02c8d7acf9f65caa09f291a519b16bd83c3fb3374b3d4ae951/pillow-12.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b87843e225e74576437fd5b6a4c2205d422754f84a06942cfaf1dc32243e45a8", size = 7040201, upload-time = "2025-10-15T18:22:14.813Z" }, + { url = "https://files.pythonhosted.org/packages/dc/4d/435c8ac688c54d11755aedfdd9f29c9eeddf68d150fe42d1d3dbd2365149/pillow-12.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c607c90ba67533e1b2355b821fef6764d1dd2cbe26b8c1005ae84f7aea25ff79", size = 6462334, upload-time = "2025-10-15T18:22:16.375Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f2/ad34167a8059a59b8ad10bc5c72d4d9b35acc6b7c0877af8ac885b5f2044/pillow-12.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21f241bdd5080a15bc86d3466a9f6074a9c2c2b314100dd896ac81ee6db2f1ba", size = 7134162, upload-time = "2025-10-15T18:22:17.996Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b1/a7391df6adacf0a5c2cf6ac1cf1fcc1369e7d439d28f637a847f8803beb3/pillow-12.0.0-cp312-cp312-win32.whl", hash = "sha256:dd333073e0cacdc3089525c7df7d39b211bcdf31fc2824e49d01c6b6187b07d0", size = 6298769, upload-time = "2025-10-15T18:22:19.923Z" }, + { url = "https://files.pythonhosted.org/packages/a2/0b/d87733741526541c909bbf159e338dcace4f982daac6e5a8d6be225ca32d/pillow-12.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe611163f6303d1619bbcb653540a4d60f9e55e622d60a3108be0d5b441017a", size = 7001107, upload-time = "2025-10-15T18:22:21.644Z" }, + { url = "https://files.pythonhosted.org/packages/bc/96/aaa61ce33cc98421fb6088af2a03be4157b1e7e0e87087c888e2370a7f45/pillow-12.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:7dfb439562f234f7d57b1ac6bc8fe7f838a4bd49c79230e0f6a1da93e82f1fad", size = 2436012, upload-time = "2025-10-15T18:22:23.621Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/de993bb2d21b33a98d031ecf6a978e4b61da207bef02f7b43093774c480d/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643", size = 4045493, upload-time = "2025-10-15T18:22:25.758Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b6/bc8d0c4c9f6f111a783d045310945deb769b806d7574764234ffd50bc5ea/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4", size = 4120461, upload-time = "2025-10-15T18:22:27.286Z" }, + { url = "https://files.pythonhosted.org/packages/5d/57/d60d343709366a353dc56adb4ee1e7d8a2cc34e3fbc22905f4167cfec119/pillow-12.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399", size = 3576912, upload-time = "2025-10-15T18:22:28.751Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a4/a0a31467e3f83b94d37568294b01d22b43ae3c5d85f2811769b9c66389dd/pillow-12.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5", size = 5249132, upload-time = "2025-10-15T18:22:30.641Z" }, + { url = "https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b", size = 4650099, upload-time = "2025-10-15T18:22:32.73Z" }, + { url = "https://files.pythonhosted.org/packages/fc/bd/69ed99fd46a8dba7c1887156d3572fe4484e3f031405fcc5a92e31c04035/pillow-12.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3", size = 6230808, upload-time = "2025-10-15T18:22:34.337Z" }, + { url = "https://files.pythonhosted.org/packages/ea/94/8fad659bcdbf86ed70099cb60ae40be6acca434bbc8c4c0d4ef356d7e0de/pillow-12.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07", size = 8037804, upload-time = "2025-10-15T18:22:36.402Z" }, + { url = "https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e", size = 6345553, upload-time = "2025-10-15T18:22:38.066Z" }, + { url = "https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344", size = 7037729, upload-time = "2025-10-15T18:22:39.769Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b6/7e94f4c41d238615674d06ed677c14883103dce1c52e4af16f000338cfd7/pillow-12.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27", size = 6459789, upload-time = "2025-10-15T18:22:41.437Z" }, + { url = "https://files.pythonhosted.org/packages/9c/14/4448bb0b5e0f22dd865290536d20ec8a23b64e2d04280b89139f09a36bb6/pillow-12.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79", size = 7130917, upload-time = "2025-10-15T18:22:43.152Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ca/16c6926cc1c015845745d5c16c9358e24282f1e588237a4c36d2b30f182f/pillow-12.0.0-cp313-cp313-win32.whl", hash = "sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098", size = 6302391, upload-time = "2025-10-15T18:22:44.753Z" }, + { url = "https://files.pythonhosted.org/packages/6d/2a/dd43dcfd6dae9b6a49ee28a8eedb98c7d5ff2de94a5d834565164667b97b/pillow-12.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905", size = 7007477, upload-time = "2025-10-15T18:22:46.838Z" }, + { url = "https://files.pythonhosted.org/packages/77/f0/72ea067f4b5ae5ead653053212af05ce3705807906ba3f3e8f58ddf617e6/pillow-12.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a", size = 2435918, upload-time = "2025-10-15T18:22:48.399Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5e/9046b423735c21f0487ea6cb5b10f89ea8f8dfbe32576fe052b5ba9d4e5b/pillow-12.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3", size = 5251406, upload-time = "2025-10-15T18:22:49.905Z" }, + { url = "https://files.pythonhosted.org/packages/12/66/982ceebcdb13c97270ef7a56c3969635b4ee7cd45227fa707c94719229c5/pillow-12.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced", size = 4653218, upload-time = "2025-10-15T18:22:51.587Z" }, + { url = "https://files.pythonhosted.org/packages/16/b3/81e625524688c31859450119bf12674619429cab3119eec0e30a7a1029cb/pillow-12.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b", size = 6266564, upload-time = "2025-10-15T18:22:53.215Z" }, + { url = "https://files.pythonhosted.org/packages/98/59/dfb38f2a41240d2408096e1a76c671d0a105a4a8471b1871c6902719450c/pillow-12.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d", size = 8069260, upload-time = "2025-10-15T18:22:54.933Z" }, + { url = "https://files.pythonhosted.org/packages/dc/3d/378dbea5cd1874b94c312425ca77b0f47776c78e0df2df751b820c8c1d6c/pillow-12.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a", size = 6379248, upload-time = "2025-10-15T18:22:56.605Z" }, + { url = "https://files.pythonhosted.org/packages/84/b0/d525ef47d71590f1621510327acec75ae58c721dc071b17d8d652ca494d8/pillow-12.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe", size = 7066043, upload-time = "2025-10-15T18:22:58.53Z" }, + { url = "https://files.pythonhosted.org/packages/61/2c/aced60e9cf9d0cde341d54bf7932c9ffc33ddb4a1595798b3a5150c7ec4e/pillow-12.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee", size = 6490915, upload-time = "2025-10-15T18:23:00.582Z" }, + { url = "https://files.pythonhosted.org/packages/ef/26/69dcb9b91f4e59f8f34b2332a4a0a951b44f547c4ed39d3e4dcfcff48f89/pillow-12.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef", size = 7157998, upload-time = "2025-10-15T18:23:02.627Z" }, + { url = "https://files.pythonhosted.org/packages/61/2b/726235842220ca95fa441ddf55dd2382b52ab5b8d9c0596fe6b3f23dafe8/pillow-12.0.0-cp313-cp313t-win32.whl", hash = "sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9", size = 6306201, upload-time = "2025-10-15T18:23:04.709Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3d/2afaf4e840b2df71344ababf2f8edd75a705ce500e5dc1e7227808312ae1/pillow-12.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b", size = 7013165, upload-time = "2025-10-15T18:23:06.46Z" }, + { url = "https://files.pythonhosted.org/packages/6f/75/3fa09aa5cf6ed04bee3fa575798ddf1ce0bace8edb47249c798077a81f7f/pillow-12.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47", size = 2437834, upload-time = "2025-10-15T18:23:08.194Z" }, + { url = "https://files.pythonhosted.org/packages/54/2a/9a8c6ba2c2c07b71bec92cf63e03370ca5e5f5c5b119b742bcc0cde3f9c5/pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:beeae3f27f62308f1ddbcfb0690bf44b10732f2ef43758f169d5e9303165d3f9", size = 4045531, upload-time = "2025-10-15T18:23:10.121Z" }, + { url = "https://files.pythonhosted.org/packages/84/54/836fdbf1bfb3d66a59f0189ff0b9f5f666cee09c6188309300df04ad71fa/pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d4827615da15cd59784ce39d3388275ec093ae3ee8d7f0c089b76fa87af756c2", size = 4120554, upload-time = "2025-10-15T18:23:12.14Z" }, + { url = "https://files.pythonhosted.org/packages/0d/cd/16aec9f0da4793e98e6b54778a5fbce4f375c6646fe662e80600b8797379/pillow-12.0.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:3e42edad50b6909089750e65c91aa09aaf1e0a71310d383f11321b27c224ed8a", size = 3576812, upload-time = "2025-10-15T18:23:13.962Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b7/13957fda356dc46339298b351cae0d327704986337c3c69bb54628c88155/pillow-12.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e5d8efac84c9afcb40914ab49ba063d94f5dbdf5066db4482c66a992f47a3a3b", size = 5252689, upload-time = "2025-10-15T18:23:15.562Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f5/eae31a306341d8f331f43edb2e9122c7661b975433de5e447939ae61c5da/pillow-12.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:266cd5f2b63ff316d5a1bba46268e603c9caf5606d44f38c2873c380950576ad", size = 4650186, upload-time = "2025-10-15T18:23:17.379Z" }, + { url = "https://files.pythonhosted.org/packages/86/62/2a88339aa40c4c77e79108facbd307d6091e2c0eb5b8d3cf4977cfca2fe6/pillow-12.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58eea5ebe51504057dd95c5b77d21700b77615ab0243d8152793dc00eb4faf01", size = 6230308, upload-time = "2025-10-15T18:23:18.971Z" }, + { url = "https://files.pythonhosted.org/packages/c7/33/5425a8992bcb32d1cb9fa3dd39a89e613d09a22f2c8083b7bf43c455f760/pillow-12.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f13711b1a5ba512d647a0e4ba79280d3a9a045aaf7e0cc6fbe96b91d4cdf6b0c", size = 8039222, upload-time = "2025-10-15T18:23:20.909Z" }, + { url = "https://files.pythonhosted.org/packages/d8/61/3f5d3b35c5728f37953d3eec5b5f3e77111949523bd2dd7f31a851e50690/pillow-12.0.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6846bd2d116ff42cba6b646edf5bf61d37e5cbd256425fa089fee4ff5c07a99e", size = 6346657, upload-time = "2025-10-15T18:23:23.077Z" }, + { url = "https://files.pythonhosted.org/packages/3a/be/ee90a3d79271227e0f0a33c453531efd6ed14b2e708596ba5dd9be948da3/pillow-12.0.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c98fa880d695de164b4135a52fd2e9cd7b7c90a9d8ac5e9e443a24a95ef9248e", size = 7038482, upload-time = "2025-10-15T18:23:25.005Z" }, + { url = "https://files.pythonhosted.org/packages/44/34/a16b6a4d1ad727de390e9bd9f19f5f669e079e5826ec0f329010ddea492f/pillow-12.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa3ed2a29a9e9d2d488b4da81dcb54720ac3104a20bf0bd273f1e4648aff5af9", size = 6461416, upload-time = "2025-10-15T18:23:27.009Z" }, + { url = "https://files.pythonhosted.org/packages/b6/39/1aa5850d2ade7d7ba9f54e4e4c17077244ff7a2d9e25998c38a29749eb3f/pillow-12.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d034140032870024e6b9892c692fe2968493790dd57208b2c37e3fb35f6df3ab", size = 7131584, upload-time = "2025-10-15T18:23:29.752Z" }, + { url = "https://files.pythonhosted.org/packages/bf/db/4fae862f8fad0167073a7733973bfa955f47e2cac3dc3e3e6257d10fab4a/pillow-12.0.0-cp314-cp314-win32.whl", hash = "sha256:1b1b133e6e16105f524a8dec491e0586d072948ce15c9b914e41cdadd209052b", size = 6400621, upload-time = "2025-10-15T18:23:32.06Z" }, + { url = "https://files.pythonhosted.org/packages/2b/24/b350c31543fb0107ab2599464d7e28e6f856027aadda995022e695313d94/pillow-12.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:8dc232e39d409036af549c86f24aed8273a40ffa459981146829a324e0848b4b", size = 7142916, upload-time = "2025-10-15T18:23:34.71Z" }, + { url = "https://files.pythonhosted.org/packages/0f/9b/0ba5a6fd9351793996ef7487c4fdbde8d3f5f75dbedc093bb598648fddf0/pillow-12.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:d52610d51e265a51518692045e372a4c363056130d922a7351429ac9f27e70b0", size = 2523836, upload-time = "2025-10-15T18:23:36.967Z" }, + { url = "https://files.pythonhosted.org/packages/f5/7a/ceee0840aebc579af529b523d530840338ecf63992395842e54edc805987/pillow-12.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1979f4566bb96c1e50a62d9831e2ea2d1211761e5662afc545fa766f996632f6", size = 5255092, upload-time = "2025-10-15T18:23:38.573Z" }, + { url = "https://files.pythonhosted.org/packages/44/76/20776057b4bfd1aef4eeca992ebde0f53a4dce874f3ae693d0ec90a4f79b/pillow-12.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2e4b27a6e15b04832fe9bf292b94b5ca156016bbc1ea9c2c20098a0320d6cf6", size = 4653158, upload-time = "2025-10-15T18:23:40.238Z" }, + { url = "https://files.pythonhosted.org/packages/82/3f/d9ff92ace07be8836b4e7e87e6a4c7a8318d47c2f1463ffcf121fc57d9cb/pillow-12.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fb3096c30df99fd01c7bf8e544f392103d0795b9f98ba71a8054bcbf56b255f1", size = 6267882, upload-time = "2025-10-15T18:23:42.434Z" }, + { url = "https://files.pythonhosted.org/packages/9f/7a/4f7ff87f00d3ad33ba21af78bfcd2f032107710baf8280e3722ceec28cda/pillow-12.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7438839e9e053ef79f7112c881cef684013855016f928b168b81ed5835f3e75e", size = 8071001, upload-time = "2025-10-15T18:23:44.29Z" }, + { url = "https://files.pythonhosted.org/packages/75/87/fcea108944a52dad8cca0715ae6247e271eb80459364a98518f1e4f480c1/pillow-12.0.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d5c411a8eaa2299322b647cd932586b1427367fd3184ffbb8f7a219ea2041ca", size = 6380146, upload-time = "2025-10-15T18:23:46.065Z" }, + { url = "https://files.pythonhosted.org/packages/91/52/0d31b5e571ef5fd111d2978b84603fce26aba1b6092f28e941cb46570745/pillow-12.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e091d464ac59d2c7ad8e7e08105eaf9dafbc3883fd7265ffccc2baad6ac925", size = 7067344, upload-time = "2025-10-15T18:23:47.898Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f4/2dd3d721f875f928d48e83bb30a434dee75a2531bca839bb996bb0aa5a91/pillow-12.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:792a2c0be4dcc18af9d4a2dfd8a11a17d5e25274a1062b0ec1c2d79c76f3e7f8", size = 6491864, upload-time = "2025-10-15T18:23:49.607Z" }, + { url = "https://files.pythonhosted.org/packages/30/4b/667dfcf3d61fc309ba5a15b141845cece5915e39b99c1ceab0f34bf1d124/pillow-12.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:afbefa430092f71a9593a99ab6a4e7538bc9eabbf7bf94f91510d3503943edc4", size = 7158911, upload-time = "2025-10-15T18:23:51.351Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2f/16cabcc6426c32218ace36bf0d55955e813f2958afddbf1d391849fee9d1/pillow-12.0.0-cp314-cp314t-win32.whl", hash = "sha256:3830c769decf88f1289680a59d4f4c46c72573446352e2befec9a8512104fa52", size = 6408045, upload-time = "2025-10-15T18:23:53.177Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/e29aa0c9c666cf787628d3f0dcf379f4791fba79f4936d02f8b37165bdf8/pillow-12.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:905b0365b210c73afb0ebe9101a32572152dfd1c144c7e28968a331b9217b94a", size = 7148282, upload-time = "2025-10-15T18:23:55.316Z" }, + { url = "https://files.pythonhosted.org/packages/c1/70/6b41bdcddf541b437bbb9f47f94d2db5d9ddef6c37ccab8c9107743748a4/pillow-12.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7", size = 2525630, upload-time = "2025-10-15T18:23:57.149Z" }, +] + +[[package]] +name = "pycparser" +version = "2.23" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, +] + +[[package]] +name = "pygithub" +version = "2.8.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyjwt", extra = ["crypto"] }, + { name = "pynacl" }, + { name = "requests" }, + { name = "typing-extensions" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c1/74/e560bdeffea72ecb26cff27f0fad548bbff5ecc51d6a155311ea7f9e4c4c/pygithub-2.8.1.tar.gz", hash = "sha256:341b7c78521cb07324ff670afd1baa2bf5c286f8d9fd302c1798ba594a5400c9", size = 2246994, upload-time = "2025-09-02T17:41:54.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/ba/7049ce39f653f6140aac4beb53a5aaf08b4407b6a3019aae394c1c5244ff/pygithub-2.8.1-py3-none-any.whl", hash = "sha256:23a0a5bca93baef082e03411bf0ce27204c32be8bfa7abc92fe4a3e132936df0", size = 432709, upload-time = "2025-09-02T17:41:52.947Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyjwt" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + +[[package]] +name = "pynacl" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/c6/a3124dee667a423f2c637cfd262a54d67d8ccf3e160f3c50f622a85b7723/pynacl-1.6.0.tar.gz", hash = "sha256:cb36deafe6e2bce3b286e5d1f3e1c246e0ccdb8808ddb4550bb2792f2df298f2", size = 3505641, upload-time = "2025-09-10T23:39:22.308Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/24/1b639176401255605ba7c2b93a7b1eb1e379e0710eca62613633eb204201/pynacl-1.6.0-cp314-cp314t-macosx_10_10_universal2.whl", hash = "sha256:f46386c24a65383a9081d68e9c2de909b1834ec74ff3013271f1bca9c2d233eb", size = 384141, upload-time = "2025-09-10T23:38:28.675Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7b/874efdf57d6bf172db0df111b479a553c3d9e8bb4f1f69eb3ffff772d6e8/pynacl-1.6.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:dea103a1afcbc333bc0e992e64233d360d393d1e63d0bc88554f572365664348", size = 808132, upload-time = "2025-09-10T23:38:38.995Z" }, + { url = "https://files.pythonhosted.org/packages/f3/61/9b53f5913f3b75ac3d53170cdb897101b2b98afc76f4d9d3c8de5aa3ac05/pynacl-1.6.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:04f20784083014e265ad58c1b2dd562c3e35864b5394a14ab54f5d150ee9e53e", size = 1407253, upload-time = "2025-09-10T23:38:40.492Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0a/b138916b22bbf03a1bdbafecec37d714e7489dd7bcaf80cd17852f8b67be/pynacl-1.6.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bbcc4452a1eb10cd5217318c822fde4be279c9de8567f78bad24c773c21254f8", size = 843719, upload-time = "2025-09-10T23:38:30.87Z" }, + { url = "https://files.pythonhosted.org/packages/01/3b/17c368197dfb2c817ce033f94605a47d0cc27901542109e640cef263f0af/pynacl-1.6.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51fed9fe1bec9e7ff9af31cd0abba179d0e984a2960c77e8e5292c7e9b7f7b5d", size = 1445441, upload-time = "2025-09-10T23:38:33.078Z" }, + { url = "https://files.pythonhosted.org/packages/35/3c/f79b185365ab9be80cd3cd01dacf30bf5895f9b7b001e683b369e0bb6d3d/pynacl-1.6.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:10d755cf2a455d8c0f8c767a43d68f24d163b8fe93ccfaabfa7bafd26be58d73", size = 825691, upload-time = "2025-09-10T23:38:34.832Z" }, + { url = "https://files.pythonhosted.org/packages/f7/1f/8b37d25e95b8f2a434a19499a601d4d272b9839ab8c32f6b0fc1e40c383f/pynacl-1.6.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:536703b8f90e911294831a7fbcd0c062b837f3ccaa923d92a6254e11178aaf42", size = 1410726, upload-time = "2025-09-10T23:38:36.893Z" }, + { url = "https://files.pythonhosted.org/packages/bd/93/5a4a4cf9913014f83d615ad6a2df9187330f764f606246b3a744c0788c03/pynacl-1.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6b08eab48c9669d515a344fb0ef27e2cbde847721e34bba94a343baa0f33f1f4", size = 801035, upload-time = "2025-09-10T23:38:42.109Z" }, + { url = "https://files.pythonhosted.org/packages/bf/60/40da6b0fe6a4d5fd88f608389eb1df06492ba2edca93fca0b3bebff9b948/pynacl-1.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5789f016e08e5606803161ba24de01b5a345d24590a80323379fc4408832d290", size = 1371854, upload-time = "2025-09-10T23:38:44.16Z" }, + { url = "https://files.pythonhosted.org/packages/44/b2/37ac1d65008f824cba6b5bf68d18b76d97d0f62d7a032367ea69d4a187c8/pynacl-1.6.0-cp314-cp314t-win32.whl", hash = "sha256:4853c154dc16ea12f8f3ee4b7e763331876316cc3a9f06aeedf39bcdca8f9995", size = 230345, upload-time = "2025-09-10T23:38:48.276Z" }, + { url = "https://files.pythonhosted.org/packages/f4/5a/9234b7b45af890d02ebee9aae41859b9b5f15fb4a5a56d88e3b4d1659834/pynacl-1.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:347dcddce0b4d83ed3f32fd00379c83c425abee5a9d2cd0a2c84871334eaff64", size = 243103, upload-time = "2025-09-10T23:38:45.503Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2c/c1a0f19d720ab0af3bc4241af2bdf4d813c3ecdcb96392b5e1ddf2d8f24f/pynacl-1.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2d6cd56ce4998cb66a6c112fda7b1fdce5266c9f05044fa72972613bef376d15", size = 187778, upload-time = "2025-09-10T23:38:46.731Z" }, + { url = "https://files.pythonhosted.org/packages/63/37/87c72df19857c5b3b47ace6f211a26eb862ada495cc96daa372d96048fca/pynacl-1.6.0-cp38-abi3-macosx_10_10_universal2.whl", hash = "sha256:f4b3824920e206b4f52abd7de621ea7a44fd3cb5c8daceb7c3612345dfc54f2e", size = 382610, upload-time = "2025-09-10T23:38:49.459Z" }, + { url = "https://files.pythonhosted.org/packages/0c/64/3ce958a5817fd3cc6df4ec14441c43fd9854405668d73babccf77f9597a3/pynacl-1.6.0-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:16dd347cdc8ae0b0f6187a2608c0af1c8b7ecbbe6b4a06bff8253c192f696990", size = 798744, upload-time = "2025-09-10T23:38:58.531Z" }, + { url = "https://files.pythonhosted.org/packages/e4/8a/3f0dd297a0a33fa3739c255feebd0206bb1df0b44c52fbe2caf8e8bc4425/pynacl-1.6.0-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:16c60daceee88d04f8d41d0a4004a7ed8d9a5126b997efd2933e08e93a3bd850", size = 1397879, upload-time = "2025-09-10T23:39:00.44Z" }, + { url = "https://files.pythonhosted.org/packages/41/94/028ff0434a69448f61348d50d2c147dda51aabdd4fbc93ec61343332174d/pynacl-1.6.0-cp38-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25720bad35dfac34a2bcdd61d9e08d6bfc6041bebc7751d9c9f2446cf1e77d64", size = 833907, upload-time = "2025-09-10T23:38:50.936Z" }, + { url = "https://files.pythonhosted.org/packages/52/bc/a5cff7f8c30d5f4c26a07dfb0bcda1176ab8b2de86dda3106c00a02ad787/pynacl-1.6.0-cp38-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bfaa0a28a1ab718bad6239979a5a57a8d1506d0caf2fba17e524dbb409441cf", size = 1436649, upload-time = "2025-09-10T23:38:52.783Z" }, + { url = "https://files.pythonhosted.org/packages/7a/20/c397be374fd5d84295046e398de4ba5f0722dc14450f65db76a43c121471/pynacl-1.6.0-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ef214b90556bb46a485b7da8258e59204c244b1b5b576fb71848819b468c44a7", size = 817142, upload-time = "2025-09-10T23:38:54.4Z" }, + { url = "https://files.pythonhosted.org/packages/12/30/5efcef3406940cda75296c6d884090b8a9aad2dcc0c304daebb5ae99fb4a/pynacl-1.6.0-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:49c336dd80ea54780bcff6a03ee1a476be1612423010472e60af83452aa0f442", size = 1401794, upload-time = "2025-09-10T23:38:56.614Z" }, + { url = "https://files.pythonhosted.org/packages/be/e1/a8fe1248cc17ccb03b676d80fa90763760a6d1247da434844ea388d0816c/pynacl-1.6.0-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f3482abf0f9815e7246d461fab597aa179b7524628a4bc36f86a7dc418d2608d", size = 772161, upload-time = "2025-09-10T23:39:01.93Z" }, + { url = "https://files.pythonhosted.org/packages/a3/76/8a62702fb657d6d9104ce13449db221a345665d05e6a3fdefb5a7cafd2ad/pynacl-1.6.0-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:140373378e34a1f6977e573033d1dd1de88d2a5d90ec6958c9485b2fd9f3eb90", size = 1370720, upload-time = "2025-09-10T23:39:03.531Z" }, + { url = "https://files.pythonhosted.org/packages/6d/38/9e9e9b777a1c4c8204053733e1a0269672c0bd40852908c9ad6b6eaba82c/pynacl-1.6.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6b393bc5e5a0eb86bb85b533deb2d2c815666665f840a09e0aa3362bb6088736", size = 791252, upload-time = "2025-09-10T23:39:05.058Z" }, + { url = "https://files.pythonhosted.org/packages/63/ef/d972ce3d92ae05c9091363cf185e8646933f91c376e97b8be79ea6e96c22/pynacl-1.6.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4a25cfede801f01e54179b8ff9514bd7b5944da560b7040939732d1804d25419", size = 1362910, upload-time = "2025-09-10T23:39:06.924Z" }, + { url = "https://files.pythonhosted.org/packages/35/2c/ee0b373a1861f66a7ca8bdb999331525615061320dd628527a50ba8e8a60/pynacl-1.6.0-cp38-abi3-win32.whl", hash = "sha256:dcdeb41c22ff3c66eef5e63049abf7639e0db4edee57ba70531fc1b6b133185d", size = 226461, upload-time = "2025-09-10T23:39:11.894Z" }, + { url = "https://files.pythonhosted.org/packages/75/f7/41b6c0b9dd9970173b6acc026bab7b4c187e4e5beef2756d419ad65482da/pynacl-1.6.0-cp38-abi3-win_amd64.whl", hash = "sha256:cf831615cc16ba324240de79d925eacae8265b7691412ac6b24221db157f6bd1", size = 238802, upload-time = "2025-09-10T23:39:08.966Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0f/462326910c6172fa2c6ed07922b22ffc8e77432b3affffd9e18f444dbfbb/pynacl-1.6.0-cp38-abi3-win_arm64.whl", hash = "sha256:84709cea8f888e618c21ed9a0efdb1a59cc63141c403db8bf56c469b71ad56f2", size = 183846, upload-time = "2025-09-10T23:39:10.552Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "rich" +version = "14.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.28.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/48/dc/95f074d43452b3ef5d06276696ece4b3b5d696e7c9ad7173c54b1390cd70/rpds_py-0.28.0.tar.gz", hash = "sha256:abd4df20485a0983e2ca334a216249b6186d6e3c1627e106651943dbdb791aea", size = 27419, upload-time = "2025-10-22T22:24:29.327Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/5c/6c3936495003875fe7b14f90ea812841a08fca50ab26bd840e924097d9c8/rpds_py-0.28.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6b4f28583a4f247ff60cd7bdda83db8c3f5b05a7a82ff20dd4b078571747708f", size = 366439, upload-time = "2025-10-22T22:22:04.525Z" }, + { url = "https://files.pythonhosted.org/packages/56/f9/a0f1ca194c50aa29895b442771f036a25b6c41a35e4f35b1a0ea713bedae/rpds_py-0.28.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d678e91b610c29c4b3d52a2c148b641df2b4676ffe47c59f6388d58b99cdc424", size = 348170, upload-time = "2025-10-22T22:22:06.397Z" }, + { url = "https://files.pythonhosted.org/packages/18/ea/42d243d3a586beb72c77fa5def0487daf827210069a95f36328e869599ea/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e819e0e37a44a78e1383bf1970076e2ccc4dc8c2bbaa2f9bd1dc987e9afff628", size = 378838, upload-time = "2025-10-22T22:22:07.932Z" }, + { url = "https://files.pythonhosted.org/packages/e7/78/3de32e18a94791af8f33601402d9d4f39613136398658412a4e0b3047327/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5ee514e0f0523db5d3fb171f397c54875dbbd69760a414dccf9d4d7ad628b5bd", size = 393299, upload-time = "2025-10-22T22:22:09.435Z" }, + { url = "https://files.pythonhosted.org/packages/13/7e/4bdb435afb18acea2eb8a25ad56b956f28de7c59f8a1d32827effa0d4514/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f3fa06d27fdcee47f07a39e02862da0100cb4982508f5ead53ec533cd5fe55e", size = 518000, upload-time = "2025-10-22T22:22:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/31/d0/5f52a656875cdc60498ab035a7a0ac8f399890cc1ee73ebd567bac4e39ae/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46959ef2e64f9e4a41fc89aa20dbca2b85531f9a72c21099a3360f35d10b0d5a", size = 408746, upload-time = "2025-10-22T22:22:13.143Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/49ce51767b879cde77e7ad9fae164ea15dce3616fe591d9ea1df51152706/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8455933b4bcd6e83fde3fefc987a023389c4b13f9a58c8d23e4b3f6d13f78c84", size = 386379, upload-time = "2025-10-22T22:22:14.602Z" }, + { url = "https://files.pythonhosted.org/packages/6a/99/e4e1e1ee93a98f72fc450e36c0e4d99c35370220e815288e3ecd2ec36a2a/rpds_py-0.28.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:ad50614a02c8c2962feebe6012b52f9802deec4263946cddea37aaf28dd25a66", size = 401280, upload-time = "2025-10-22T22:22:16.063Z" }, + { url = "https://files.pythonhosted.org/packages/61/35/e0c6a57488392a8b319d2200d03dad2b29c0db9996f5662c3b02d0b86c02/rpds_py-0.28.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e5deca01b271492553fdb6c7fd974659dce736a15bae5dad7ab8b93555bceb28", size = 412365, upload-time = "2025-10-22T22:22:17.504Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6a/841337980ea253ec797eb084665436007a1aad0faac1ba097fb906c5f69c/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:735f8495a13159ce6a0d533f01e8674cec0c57038c920495f87dcb20b3ddb48a", size = 559573, upload-time = "2025-10-22T22:22:19.108Z" }, + { url = "https://files.pythonhosted.org/packages/e7/5e/64826ec58afd4c489731f8b00729c5f6afdb86f1df1df60bfede55d650bb/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:961ca621ff10d198bbe6ba4957decca61aa2a0c56695384c1d6b79bf61436df5", size = 583973, upload-time = "2025-10-22T22:22:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ee/44d024b4843f8386a4eeaa4c171b3d31d55f7177c415545fd1a24c249b5d/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2374e16cc9131022e7d9a8f8d65d261d9ba55048c78f3b6e017971a4f5e6353c", size = 553800, upload-time = "2025-10-22T22:22:22.25Z" }, + { url = "https://files.pythonhosted.org/packages/7d/89/33e675dccff11a06d4d85dbb4d1865f878d5020cbb69b2c1e7b2d3f82562/rpds_py-0.28.0-cp312-cp312-win32.whl", hash = "sha256:d15431e334fba488b081d47f30f091e5d03c18527c325386091f31718952fe08", size = 216954, upload-time = "2025-10-22T22:22:24.105Z" }, + { url = "https://files.pythonhosted.org/packages/af/36/45f6ebb3210887e8ee6dbf1bc710ae8400bb417ce165aaf3024b8360d999/rpds_py-0.28.0-cp312-cp312-win_amd64.whl", hash = "sha256:a410542d61fc54710f750d3764380b53bf09e8c4edbf2f9141a82aa774a04f7c", size = 227844, upload-time = "2025-10-22T22:22:25.551Z" }, + { url = "https://files.pythonhosted.org/packages/57/91/f3fb250d7e73de71080f9a221d19bd6a1c1eb0d12a1ea26513f6c1052ad6/rpds_py-0.28.0-cp312-cp312-win_arm64.whl", hash = "sha256:1f0cfd1c69e2d14f8c892b893997fa9a60d890a0c8a603e88dca4955f26d1edd", size = 217624, upload-time = "2025-10-22T22:22:26.914Z" }, + { url = "https://files.pythonhosted.org/packages/d3/03/ce566d92611dfac0085c2f4b048cd53ed7c274a5c05974b882a908d540a2/rpds_py-0.28.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e9e184408a0297086f880556b6168fa927d677716f83d3472ea333b42171ee3b", size = 366235, upload-time = "2025-10-22T22:22:28.397Z" }, + { url = "https://files.pythonhosted.org/packages/00/34/1c61da1b25592b86fd285bd7bd8422f4c9d748a7373b46126f9ae792a004/rpds_py-0.28.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:edd267266a9b0448f33dc465a97cfc5d467594b600fe28e7fa2f36450e03053a", size = 348241, upload-time = "2025-10-22T22:22:30.171Z" }, + { url = "https://files.pythonhosted.org/packages/fc/00/ed1e28616848c61c493a067779633ebf4b569eccaacf9ccbdc0e7cba2b9d/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85beb8b3f45e4e32f6802fb6cd6b17f615ef6c6a52f265371fb916fae02814aa", size = 378079, upload-time = "2025-10-22T22:22:31.644Z" }, + { url = "https://files.pythonhosted.org/packages/11/b2/ccb30333a16a470091b6e50289adb4d3ec656fd9951ba8c5e3aaa0746a67/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d2412be8d00a1b895f8ad827cc2116455196e20ed994bb704bf138fe91a42724", size = 393151, upload-time = "2025-10-22T22:22:33.453Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d0/73e2217c3ee486d555cb84920597480627d8c0240ff3062005c6cc47773e/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cf128350d384b777da0e68796afdcebc2e9f63f0e9f242217754e647f6d32491", size = 517520, upload-time = "2025-10-22T22:22:34.949Z" }, + { url = "https://files.pythonhosted.org/packages/c4/91/23efe81c700427d0841a4ae7ea23e305654381831e6029499fe80be8a071/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2036d09b363aa36695d1cc1a97b36865597f4478470b0697b5ee9403f4fe399", size = 408699, upload-time = "2025-10-22T22:22:36.584Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ee/a324d3198da151820a326c1f988caaa4f37fc27955148a76fff7a2d787a9/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8e1e9be4fa6305a16be628959188e4fd5cd6f1b0e724d63c6d8b2a8adf74ea6", size = 385720, upload-time = "2025-10-22T22:22:38.014Z" }, + { url = "https://files.pythonhosted.org/packages/19/ad/e68120dc05af8b7cab4a789fccd8cdcf0fe7e6581461038cc5c164cd97d2/rpds_py-0.28.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0a403460c9dd91a7f23fc3188de6d8977f1d9603a351d5db6cf20aaea95b538d", size = 401096, upload-time = "2025-10-22T22:22:39.869Z" }, + { url = "https://files.pythonhosted.org/packages/99/90/c1e070620042459d60df6356b666bb1f62198a89d68881816a7ed121595a/rpds_py-0.28.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d7366b6553cdc805abcc512b849a519167db8f5e5c3472010cd1228b224265cb", size = 411465, upload-time = "2025-10-22T22:22:41.395Z" }, + { url = "https://files.pythonhosted.org/packages/68/61/7c195b30d57f1b8d5970f600efee72a4fad79ec829057972e13a0370fd24/rpds_py-0.28.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b43c6a3726efd50f18d8120ec0551241c38785b68952d240c45ea553912ac41", size = 558832, upload-time = "2025-10-22T22:22:42.871Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3d/06f3a718864773f69941d4deccdf18e5e47dd298b4628062f004c10f3b34/rpds_py-0.28.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0cb7203c7bc69d7c1585ebb33a2e6074492d2fc21ad28a7b9d40457ac2a51ab7", size = 583230, upload-time = "2025-10-22T22:22:44.877Z" }, + { url = "https://files.pythonhosted.org/packages/66/df/62fc783781a121e77fee9a21ead0a926f1b652280a33f5956a5e7833ed30/rpds_py-0.28.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a52a5169c664dfb495882adc75c304ae1d50df552fbd68e100fdc719dee4ff9", size = 553268, upload-time = "2025-10-22T22:22:46.441Z" }, + { url = "https://files.pythonhosted.org/packages/84/85/d34366e335140a4837902d3dea89b51f087bd6a63c993ebdff59e93ee61d/rpds_py-0.28.0-cp313-cp313-win32.whl", hash = "sha256:2e42456917b6687215b3e606ab46aa6bca040c77af7df9a08a6dcfe8a4d10ca5", size = 217100, upload-time = "2025-10-22T22:22:48.342Z" }, + { url = "https://files.pythonhosted.org/packages/3c/1c/f25a3f3752ad7601476e3eff395fe075e0f7813fbb9862bd67c82440e880/rpds_py-0.28.0-cp313-cp313-win_amd64.whl", hash = "sha256:e0a0311caedc8069d68fc2bf4c9019b58a2d5ce3cd7cb656c845f1615b577e1e", size = 227759, upload-time = "2025-10-22T22:22:50.219Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d6/5f39b42b99615b5bc2f36ab90423ea404830bdfee1c706820943e9a645eb/rpds_py-0.28.0-cp313-cp313-win_arm64.whl", hash = "sha256:04c1b207ab8b581108801528d59ad80aa83bb170b35b0ddffb29c20e411acdc1", size = 217326, upload-time = "2025-10-22T22:22:51.647Z" }, + { url = "https://files.pythonhosted.org/packages/5c/8b/0c69b72d1cee20a63db534be0df271effe715ef6c744fdf1ff23bb2b0b1c/rpds_py-0.28.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f296ea3054e11fc58ad42e850e8b75c62d9a93a9f981ad04b2e5ae7d2186ff9c", size = 355736, upload-time = "2025-10-22T22:22:53.211Z" }, + { url = "https://files.pythonhosted.org/packages/f7/6d/0c2ee773cfb55c31a8514d2cece856dd299170a49babd50dcffb15ddc749/rpds_py-0.28.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5a7306c19b19005ad98468fcefeb7100b19c79fc23a5f24a12e06d91181193fa", size = 342677, upload-time = "2025-10-22T22:22:54.723Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1c/22513ab25a27ea205144414724743e305e8153e6abe81833b5e678650f5a/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5d9b86aa501fed9862a443c5c3116f6ead8bc9296185f369277c42542bd646b", size = 371847, upload-time = "2025-10-22T22:22:56.295Z" }, + { url = "https://files.pythonhosted.org/packages/60/07/68e6ccdb4b05115ffe61d31afc94adef1833d3a72f76c9632d4d90d67954/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e5bbc701eff140ba0e872691d573b3d5d30059ea26e5785acba9132d10c8c31d", size = 381800, upload-time = "2025-10-22T22:22:57.808Z" }, + { url = "https://files.pythonhosted.org/packages/73/bf/6d6d15df80781d7f9f368e7c1a00caf764436518c4877fb28b029c4624af/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a5690671cd672a45aa8616d7374fdf334a1b9c04a0cac3c854b1136e92374fe", size = 518827, upload-time = "2025-10-22T22:22:59.826Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d3/2decbb2976cc452cbf12a2b0aaac5f1b9dc5dd9d1f7e2509a3ee00421249/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9f1d92ecea4fa12f978a367c32a5375a1982834649cdb96539dcdc12e609ab1a", size = 399471, upload-time = "2025-10-22T22:23:01.968Z" }, + { url = "https://files.pythonhosted.org/packages/b1/2c/f30892f9e54bd02e5faca3f6a26d6933c51055e67d54818af90abed9748e/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d252db6b1a78d0a3928b6190156042d54c93660ce4d98290d7b16b5296fb7cc", size = 377578, upload-time = "2025-10-22T22:23:03.52Z" }, + { url = "https://files.pythonhosted.org/packages/f0/5d/3bce97e5534157318f29ac06bf2d279dae2674ec12f7cb9c12739cee64d8/rpds_py-0.28.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d61b355c3275acb825f8777d6c4505f42b5007e357af500939d4a35b19177259", size = 390482, upload-time = "2025-10-22T22:23:05.391Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f0/886bd515ed457b5bd93b166175edb80a0b21a210c10e993392127f1e3931/rpds_py-0.28.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:acbe5e8b1026c0c580d0321c8aae4b0a1e1676861d48d6e8c6586625055b606a", size = 402447, upload-time = "2025-10-22T22:23:06.93Z" }, + { url = "https://files.pythonhosted.org/packages/42/b5/71e8777ac55e6af1f4f1c05b47542a1eaa6c33c1cf0d300dca6a1c6e159a/rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8aa23b6f0fc59b85b4c7d89ba2965af274346f738e8d9fc2455763602e62fd5f", size = 552385, upload-time = "2025-10-22T22:23:08.557Z" }, + { url = "https://files.pythonhosted.org/packages/5d/cb/6ca2d70cbda5a8e36605e7788c4aa3bea7c17d71d213465a5a675079b98d/rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7b14b0c680286958817c22d76fcbca4800ddacef6f678f3a7c79a1fe7067fe37", size = 575642, upload-time = "2025-10-22T22:23:10.348Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d4/407ad9960ca7856d7b25c96dcbe019270b5ffdd83a561787bc682c797086/rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bcf1d210dfee61a6c86551d67ee1031899c0fdbae88b2d44a569995d43797712", size = 544507, upload-time = "2025-10-22T22:23:12.434Z" }, + { url = "https://files.pythonhosted.org/packages/51/31/2f46fe0efcac23fbf5797c6b6b7e1c76f7d60773e525cb65fcbc582ee0f2/rpds_py-0.28.0-cp313-cp313t-win32.whl", hash = "sha256:3aa4dc0fdab4a7029ac63959a3ccf4ed605fee048ba67ce89ca3168da34a1342", size = 205376, upload-time = "2025-10-22T22:23:13.979Z" }, + { url = "https://files.pythonhosted.org/packages/92/e4/15947bda33cbedfc134490a41841ab8870a72a867a03d4969d886f6594a2/rpds_py-0.28.0-cp313-cp313t-win_amd64.whl", hash = "sha256:7b7d9d83c942855e4fdcfa75d4f96f6b9e272d42fffcb72cd4bb2577db2e2907", size = 215907, upload-time = "2025-10-22T22:23:15.5Z" }, + { url = "https://files.pythonhosted.org/packages/08/47/ffe8cd7a6a02833b10623bf765fbb57ce977e9a4318ca0e8cf97e9c3d2b3/rpds_py-0.28.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:dcdcb890b3ada98a03f9f2bb108489cdc7580176cb73b4f2d789e9a1dac1d472", size = 353830, upload-time = "2025-10-22T22:23:17.03Z" }, + { url = "https://files.pythonhosted.org/packages/f9/9f/890f36cbd83a58491d0d91ae0db1702639edb33fb48eeb356f80ecc6b000/rpds_py-0.28.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f274f56a926ba2dc02976ca5b11c32855cbd5925534e57cfe1fda64e04d1add2", size = 341819, upload-time = "2025-10-22T22:23:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/09/e3/921eb109f682aa24fb76207698fbbcf9418738f35a40c21652c29053f23d/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fe0438ac4a29a520ea94c8c7f1754cdd8feb1bc490dfda1bfd990072363d527", size = 373127, upload-time = "2025-10-22T22:23:20.216Z" }, + { url = "https://files.pythonhosted.org/packages/23/13/bce4384d9f8f4989f1a9599c71b7a2d877462e5fd7175e1f69b398f729f4/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a358a32dd3ae50e933347889b6af9a1bdf207ba5d1a3f34e1a38cd3540e6733", size = 382767, upload-time = "2025-10-22T22:23:21.787Z" }, + { url = "https://files.pythonhosted.org/packages/23/e1/579512b2d89a77c64ccef5a0bc46a6ef7f72ae0cf03d4b26dcd52e57ee0a/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e80848a71c78aa328fefaba9c244d588a342c8e03bda518447b624ea64d1ff56", size = 517585, upload-time = "2025-10-22T22:23:23.699Z" }, + { url = "https://files.pythonhosted.org/packages/62/3c/ca704b8d324a2591b0b0adcfcaadf9c862375b11f2f667ac03c61b4fd0a6/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f586db2e209d54fe177e58e0bc4946bea5fb0102f150b1b2f13de03e1f0976f8", size = 399828, upload-time = "2025-10-22T22:23:25.713Z" }, + { url = "https://files.pythonhosted.org/packages/da/37/e84283b9e897e3adc46b4c88bb3f6ec92a43bd4d2f7ef5b13459963b2e9c/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ae8ee156d6b586e4292491e885d41483136ab994e719a13458055bec14cf370", size = 375509, upload-time = "2025-10-22T22:23:27.32Z" }, + { url = "https://files.pythonhosted.org/packages/1a/c2/a980beab869d86258bf76ec42dec778ba98151f253a952b02fe36d72b29c/rpds_py-0.28.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:a805e9b3973f7e27f7cab63a6b4f61d90f2e5557cff73b6e97cd5b8540276d3d", size = 392014, upload-time = "2025-10-22T22:23:29.332Z" }, + { url = "https://files.pythonhosted.org/packages/da/b5/b1d3c5f9d3fa5aeef74265f9c64de3c34a0d6d5cd3c81c8b17d5c8f10ed4/rpds_py-0.28.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5d3fd16b6dc89c73a4da0b4ac8b12a7ecc75b2864b95c9e5afed8003cb50a728", size = 402410, upload-time = "2025-10-22T22:23:31.14Z" }, + { url = "https://files.pythonhosted.org/packages/74/ae/cab05ff08dfcc052afc73dcb38cbc765ffc86f94e966f3924cd17492293c/rpds_py-0.28.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6796079e5d24fdaba6d49bda28e2c47347e89834678f2bc2c1b4fc1489c0fb01", size = 553593, upload-time = "2025-10-22T22:23:32.834Z" }, + { url = "https://files.pythonhosted.org/packages/70/80/50d5706ea2a9bfc9e9c5f401d91879e7c790c619969369800cde202da214/rpds_py-0.28.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:76500820c2af232435cbe215e3324c75b950a027134e044423f59f5b9a1ba515", size = 576925, upload-time = "2025-10-22T22:23:34.47Z" }, + { url = "https://files.pythonhosted.org/packages/ab/12/85a57d7a5855a3b188d024b099fd09c90db55d32a03626d0ed16352413ff/rpds_py-0.28.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bbdc5640900a7dbf9dd707fe6388972f5bbd883633eb68b76591044cfe346f7e", size = 542444, upload-time = "2025-10-22T22:23:36.093Z" }, + { url = "https://files.pythonhosted.org/packages/6c/65/10643fb50179509150eb94d558e8837c57ca8b9adc04bd07b98e57b48f8c/rpds_py-0.28.0-cp314-cp314-win32.whl", hash = "sha256:adc8aa88486857d2b35d75f0640b949759f79dc105f50aa2c27816b2e0dd749f", size = 207968, upload-time = "2025-10-22T22:23:37.638Z" }, + { url = "https://files.pythonhosted.org/packages/b4/84/0c11fe4d9aaea784ff4652499e365963222481ac647bcd0251c88af646eb/rpds_py-0.28.0-cp314-cp314-win_amd64.whl", hash = "sha256:66e6fa8e075b58946e76a78e69e1a124a21d9a48a5b4766d15ba5b06869d1fa1", size = 218876, upload-time = "2025-10-22T22:23:39.179Z" }, + { url = "https://files.pythonhosted.org/packages/0f/e0/3ab3b86ded7bb18478392dc3e835f7b754cd446f62f3fc96f4fe2aca78f6/rpds_py-0.28.0-cp314-cp314-win_arm64.whl", hash = "sha256:a6fe887c2c5c59413353b7c0caff25d0e566623501ccfff88957fa438a69377d", size = 212506, upload-time = "2025-10-22T22:23:40.755Z" }, + { url = "https://files.pythonhosted.org/packages/51/ec/d5681bb425226c3501eab50fc30e9d275de20c131869322c8a1729c7b61c/rpds_py-0.28.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7a69df082db13c7070f7b8b1f155fa9e687f1d6aefb7b0e3f7231653b79a067b", size = 355433, upload-time = "2025-10-22T22:23:42.259Z" }, + { url = "https://files.pythonhosted.org/packages/be/ec/568c5e689e1cfb1ea8b875cffea3649260955f677fdd7ddc6176902d04cd/rpds_py-0.28.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b1cde22f2c30ebb049a9e74c5374994157b9b70a16147d332f89c99c5960737a", size = 342601, upload-time = "2025-10-22T22:23:44.372Z" }, + { url = "https://files.pythonhosted.org/packages/32/fe/51ada84d1d2a1d9d8f2c902cfddd0133b4a5eb543196ab5161d1c07ed2ad/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5338742f6ba7a51012ea470bd4dc600a8c713c0c72adaa0977a1b1f4327d6592", size = 372039, upload-time = "2025-10-22T22:23:46.025Z" }, + { url = "https://files.pythonhosted.org/packages/07/c1/60144a2f2620abade1a78e0d91b298ac2d9b91bc08864493fa00451ef06e/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1460ebde1bcf6d496d80b191d854adedcc619f84ff17dc1c6d550f58c9efbba", size = 382407, upload-time = "2025-10-22T22:23:48.098Z" }, + { url = "https://files.pythonhosted.org/packages/45/ed/091a7bbdcf4038a60a461df50bc4c82a7ed6d5d5e27649aab61771c17585/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e3eb248f2feba84c692579257a043a7699e28a77d86c77b032c1d9fbb3f0219c", size = 518172, upload-time = "2025-10-22T22:23:50.16Z" }, + { url = "https://files.pythonhosted.org/packages/54/dd/02cc90c2fd9c2ef8016fd7813bfacd1c3a1325633ec8f244c47b449fc868/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3bbba5def70b16cd1c1d7255666aad3b290fbf8d0fe7f9f91abafb73611a91", size = 399020, upload-time = "2025-10-22T22:23:51.81Z" }, + { url = "https://files.pythonhosted.org/packages/ab/81/5d98cc0329bbb911ccecd0b9e19fbf7f3a5de8094b4cda5e71013b2dd77e/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3114f4db69ac5a1f32e7e4d1cbbe7c8f9cf8217f78e6e002cedf2d54c2a548ed", size = 377451, upload-time = "2025-10-22T22:23:53.711Z" }, + { url = "https://files.pythonhosted.org/packages/b4/07/4d5bcd49e3dfed2d38e2dcb49ab6615f2ceb9f89f5a372c46dbdebb4e028/rpds_py-0.28.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4b0cb8a906b1a0196b863d460c0222fb8ad0f34041568da5620f9799b83ccf0b", size = 390355, upload-time = "2025-10-22T22:23:55.299Z" }, + { url = "https://files.pythonhosted.org/packages/3f/79/9f14ba9010fee74e4f40bf578735cfcbb91d2e642ffd1abe429bb0b96364/rpds_py-0.28.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf681ac76a60b667106141e11a92a3330890257e6f559ca995fbb5265160b56e", size = 403146, upload-time = "2025-10-22T22:23:56.929Z" }, + { url = "https://files.pythonhosted.org/packages/39/4c/f08283a82ac141331a83a40652830edd3a4a92c34e07e2bbe00baaea2f5f/rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1e8ee6413cfc677ce8898d9cde18cc3a60fc2ba756b0dec5b71eb6eb21c49fa1", size = 552656, upload-time = "2025-10-22T22:23:58.62Z" }, + { url = "https://files.pythonhosted.org/packages/61/47/d922fc0666f0dd8e40c33990d055f4cc6ecff6f502c2d01569dbed830f9b/rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b3072b16904d0b5572a15eb9d31c1954e0d3227a585fc1351aa9878729099d6c", size = 576782, upload-time = "2025-10-22T22:24:00.312Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0c/5bafdd8ccf6aa9d3bfc630cfece457ff5b581af24f46a9f3590f790e3df2/rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b670c30fd87a6aec281c3c9896d3bae4b205fd75d79d06dc87c2503717e46092", size = 544671, upload-time = "2025-10-22T22:24:02.297Z" }, + { url = "https://files.pythonhosted.org/packages/2c/37/dcc5d8397caa924988693519069d0beea077a866128719351a4ad95e82fc/rpds_py-0.28.0-cp314-cp314t-win32.whl", hash = "sha256:8014045a15b4d2b3476f0a287fcc93d4f823472d7d1308d47884ecac9e612be3", size = 205749, upload-time = "2025-10-22T22:24:03.848Z" }, + { url = "https://files.pythonhosted.org/packages/d7/69/64d43b21a10d72b45939a28961216baeb721cc2a430f5f7c3bfa21659a53/rpds_py-0.28.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7a4e59c90d9c27c561eb3160323634a9ff50b04e4f7820600a2beb0ac90db578", size = 216233, upload-time = "2025-10-22T22:24:05.471Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] diff --git a/template-repos.yml b/template-repos.yml new file mode 100644 index 00000000..df6d991f --- /dev/null +++ b/template-repos.yml @@ -0,0 +1,142 @@ +- url: https://github.com/Bendemeurichy/FlowSOM_parallel +- url: https://github.com/BioImageTools/ngff-transformations +- url: https://github.com/Boehringer-Ingelheim/dso +- url: https://github.com/Boehringer-Ingelheim/dso-mgr +- url: https://github.com/BoevaLab/infercnvpy +- url: https://github.com/COMBINE-lab/QCatch +- url: https://github.com/CSOgroup/cellcharter +- url: https://github.com/CSOgroup/torchgmm +- url: https://github.com/ChanghaoGong/STutils +- url: https://github.com/ChengmingZhang-CAS/CauTrigger +- url: https://github.com/CompCy-lab/scHub +- url: https://github.com/Computational-Morphogenomics-Group/Ladder +- url: https://github.com/ComputationalBiomedicineGroup/Rectangle +- url: https://github.com/David-M-P/insight +- url: https://github.com/Floto-Lab/BactGraph +- url: https://github.com/FroeseLab/bulkpy +- url: https://github.com/Gabriellvl/FlowSOM +- url: https://github.com/LiHongCSBLab/scMagnify +- url: https://github.com/Lotfollahi-lab/mintflow +- url: https://github.com/MannLabs/alphapepttools +- url: https://github.com/MannLabs/dvp-io +- url: https://github.com/NKI-CCB/sobolev_alignment +- url: https://github.com/Teichlab/multi-view-atlas +- url: https://github.com/YosefLab/cytovi-reference-implementation +- url: https://github.com/YosefLab/embedding-scvi +- url: https://github.com/YosefLab/popV +- url: https://github.com/YosefLab/pycea +- url: https://github.com/YosefLab/scib-metrics +- url: https://github.com/YosefLab/scvi-hub-models +- url: https://github.com/YosefLab/treedata +- url: https://github.com/YosefLab/visionpy +- url: https://github.com/Zethson/fknni +- url: https://github.com/adamgayoso/figmasvg +- url: https://github.com/aertslab/CREsted +- url: https://github.com/aertslab/TF-MINDI +- url: https://github.com/agerardy/myeditdistance +- url: https://github.com/angelolab/Nimbus-Inference +- url: https://github.com/angelolab/mbt +- url: https://github.com/angelolab/pici-vitessce +- url: https://github.com/angelolab/tonic-vitessce +- url: https://github.com/bartuschimschek/mmil-refactored +- url: https://github.com/bioFAM/mofaflex +- url: https://github.com/bioFAM/scDoRI +- url: https://github.com/bunina-lab/scDoRI_tools +- url: https://github.com/cameronraysmith/perturbvelo +- url: https://github.com/carmonalab/pyucell +- url: https://github.com/clinicalomx/napari-prism +- url: https://github.com/cobioda/scispy +- url: https://github.com/const-ae/pyLemur +- url: https://github.com/czi-ai/scldm +- url: https://github.com/d-j-k/donorpy +- url: https://github.com/data-intuitive/dummy-anndata +- url: https://github.com/davidrm-bio/DOTools_py +- url: https://github.com/decomverse/scmetric +- url: https://github.com/dertrotl/geneGATer +- url: https://github.com/devsystemslab/HNOCA-tools +- url: https://github.com/edbiomedai/scmorph +- url: https://github.com/ergonyc/lblator +- url: https://github.com/eroell/mypackage-cruft-oct +- url: https://github.com/greenelab/single_translator_VAE +- url: https://github.com/grst/karttapullautin2tiles +- url: https://github.com/grst/spatialdata-plot +- url: https://github.com/icbi-lab/atlas_protocol +- url: https://github.com/icbi-lab/infercnvpy +- url: https://github.com/icbi-lab/shears +- url: https://github.com/ilia-kats/PolarbearPlus +- url: https://github.com/immunitastx/monkeybread +- url: https://github.com/imsb-uke/nichepca +- url: https://github.com/ivirshup/binsparse-python +- url: https://github.com/jkobject/hierarchical_classifier +- url: https://github.com/jkobject/simpler_flash +- url: https://github.com/jlause/scverse-tutorials +- url: https://github.com/joechanlab/scDeBussy +- url: https://github.com/joschif/delnx +- url: https://github.com/jskerman/chronai +- url: https://github.com/karadavis-lab/nbl +- url: https://github.com/lhqing/scmallet +- url: https://github.com/lucas-diedrich/sccoral +- url: https://github.com/lueckenlab/patpy +- url: https://github.com/lzj1769/LR2net +- url: https://github.com/macwiatrak/BacBench +- url: https://github.com/macwiatrak/Bacformer +- url: https://github.com/macwiatrak/scverse-hackathon-data-4-ai +- url: https://github.com/mengerj/adata_hf_datasets +- url: https://github.com/mengerj/mmcontext +- url: https://github.com/mostafavilabuw/drum +- url: https://github.com/mumichae/scAtlasTb-utils +- url: https://github.com/nitzanlab/biolord +- url: https://github.com/peng-lab/hescape +- url: https://github.com/pinellolab/PerTurbo +- url: https://github.com/pinellolab/cell2net +- url: https://github.com/quadbio/atac_mapper +- url: https://github.com/quadbio/cell-annotator +- url: https://github.com/quadbio/cellmapper +- url: https://github.com/quadbio/scembed +- url: https://github.com/quadbio/slurm_sweep +- url: https://github.com/rushin682/spatialstream +- url: https://github.com/saeyslab/FlowSOM_Python +- url: https://github.com/scverse/annbatch +- url: https://github.com/scverse/anndata +- url: https://github.com/scverse/anndata-plot +- url: https://github.com/scverse/cookiecutter-scverse-instance + skip: true + reason: Instance repo gets updated by the bot via the template +- url: https://github.com/scverse/decoupler +- url: https://github.com/scverse/deres +- url: https://github.com/scverse/formulaic-contrasts +- url: https://github.com/scverse/genomic-features +- url: https://github.com/scverse/pertpy +- url: https://github.com/scverse/pytometry +- url: https://github.com/scverse/scanpy +- url: https://github.com/scverse/scirpy +- url: https://github.com/scverse/scverse-tutorials +- url: https://github.com/scverse/simple-scvi +- url: https://github.com/scverse/spatial-sample-aggregation +- url: https://github.com/scverse/spatialdata-plot +- url: https://github.com/scverse/squidpy +- url: https://github.com/srivarra/annsel +- url: https://github.com/srivarra/spatial-collection +- url: https://github.com/srivarra/xrdantic +- url: https://github.com/sueoglu/myeditdistance +- url: https://github.com/tansey-lab/nf-rnaseq +- url: https://github.com/tddough98/airgradient +- url: https://github.com/theislab/CellFlow +- url: https://github.com/theislab/CellFlow2 +- url: https://github.com/theislab/DRVI +- url: https://github.com/theislab/cellflow_reproducibility +- url: https://github.com/theislab/cellink +- url: https://github.com/theislab/ehrapy +- url: https://github.com/theislab/ehrdata +- url: https://github.com/theislab/geome +- url: https://github.com/theislab/mapqc +- url: https://github.com/theislab/multigrate +- url: https://github.com/theislab/multimil +- url: https://github.com/theislab/spatialdata-db +- url: https://github.com/theislab/transcription_factor_activity +- url: https://github.com/theislab/troutpy +- url: https://github.com/timtreis/gefslim +- url: https://github.com/vitkl/cell2module +- url: https://github.com/wangd12rpi/hescape_changed +- url: https://github.com/yizhak-lab-ccg/scXpand +- url: https://github.com/zunderlab/eschr