From a3dca5e99d11154e359e1c01b111a6aabef933b1 Mon Sep 17 00:00:00 2001 From: Andre Date: Fri, 18 Sep 2026 17:11:42 -0400 Subject: [PATCH 1/4] build: test on Python 3.13, and make the tox matrix run again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The matrix did not run on any version, not just the new one. Each env did `deps = poetry` plus `poetry install --no-root`, which is redundant — tox already builds the package with poetry-core and installs it with the dependencies resolved from pyproject.toml — and self-defeating: poetry sharing an env with the package under test makes the two compete over common dependencies. py312 could not find the poetry binary at all and py313 died on `No module named 'packaging.licenses'`. So the envs now declare only what the tests need on top of the runtime deps, which is pytest, and a shared [testenv] carries it. Three things had to give way for py313 to resolve: - `packaging` was pinned to exactly 24.1, which modern tox cannot live with. The pin bought nothing: the only use is `version.parse` in base_dtp.py, an API stable for years. Relaxed to >=24.1. - tox 4.23.2 breaks against virtualenv 21.x, which no longer exposes `cached_py_info.PythonInfo`. Floor raised to 4.61.5 so a re-resolve cannot walk back into it. - basepython for py313 points at Homebrew, because the local pyenv is too old to offer anything past 3.13.0a6. CI tested 3.11 alone, which would have left 3.13 unexercised, so it now runs the same four versions tox does. 760 tests pass on 3.10, 3.11, 3.12 and 3.13. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/test.yml | 9 +- poetry.lock | 503 +++++++++++++++++++++++++++++++------ pyproject.toml | 7 +- tox.ini | 32 +-- 4 files changed, 452 insertions(+), 99 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 57d24555..440983c9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,13 +9,20 @@ jobs: test: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12", "3.13"] + + name: test (py${{ matrix.python-version }}) + steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: ${{ matrix.python-version }} - name: Install Poetry run: | diff --git a/poetry.lock b/poetry.lock index f6fb324d..5541c957 100644 --- a/poetry.lock +++ b/poetry.lock @@ -51,6 +51,17 @@ files = [ astroid = ["astroid (>=2,<5)"] test = ["astroid (>=2,<5)", "pytest (<9.0)", "pytest-cov", "pytest-xdist"] +[[package]] +name = "attrs" +version = "26.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.9" +files = [ + {file = "attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}, + {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, +] + [[package]] name = "babel" version = "2.18.0" @@ -133,6 +144,24 @@ d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "bleach" +version = "6.4.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.10" +files = [ + {file = "bleach-6.4.0-py3-none-any.whl", hash = "sha256:4b6b6a54fff2e69a3dde9d21cc6301220bee3c3cb792187d11403fd795031081"}, + {file = "bleach-6.4.0.tar.gz", hash = "sha256:4202482733d85cedd04e59fcb2f89f4e4c7c385a78d3c3c23c30446843a37452"}, +] + +[package.dependencies] +tinycss2 = {version = ">=1.1.0", optional = true, markers = "extra == \"css\""} +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0)"] + [[package]] name = "cachetools" version = "7.0.5" @@ -267,42 +296,6 @@ files = [ [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} -[[package]] -name = "chardet" -version = "7.2.0" -description = "Universal character encoding detector" -optional = false -python-versions = ">=3.10" -files = [ - {file = "chardet-7.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:556d6f81bd4131f7b2d4aa535f3061cd381853d4db7ea5c0a15dd5f1a3f39b66"}, - {file = "chardet-7.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8b4c05733a517a2f53beb8d740cd6c5a1f4387c3dcbeb78380b848498fee8a6"}, - {file = "chardet-7.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce80e8b62bb88135d36b9d4b95a6d9624ea862090bfd0228f9fee4a6aafaffc8"}, - {file = "chardet-7.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8190584663b8c051db28be5174d1c5774d7b7a5112e47152c02fd50bdf6405ad"}, - {file = "chardet-7.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:dfcf826f413be2d94605ecb2089f29e189cf6ed9baa30d9b2c8868da2e142398"}, - {file = "chardet-7.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8685b331c4896e9135bd748387f713dd53c019475ae1b8238b8f59be1668acd"}, - {file = "chardet-7.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa14cc0e7d2142dd313524b3a339e15cbd8b7a8a7e11a560686e0b6f58038ec9"}, - {file = "chardet-7.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c51a3d8aa3c162be0495404b39bb1c137b44a634c1f46e2909e2c6a60349c00"}, - {file = "chardet-7.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:347ed77bb5eed8929fae7482671690a15c731d66808f1ff0ce7d22224ca7ec79"}, - {file = "chardet-7.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:d298762002a6b6e81dbcc81ade9e0882e579e968f4801daf4d8ffd6a31b99552"}, - {file = "chardet-7.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c4604344380a6f9b982c28855c1edfd23a45a2c9142b9a34bc0c08986049f398"}, - {file = "chardet-7.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:195c54d8f04a7a9c321cb7cebececa35b1c818c7aa7c195086bae10fcbb3391f"}, - {file = "chardet-7.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddd03a67fca8c91287f8718dfbe3f94c2c1aa1fd3a82433b693f5b868dedf319"}, - {file = "chardet-7.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f6af0fa005b9488c8fbf8fec2ad7023531970320901d6334c50844ccca9b117"}, - {file = "chardet-7.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:e8853c71ea1261bcc1b8f8b171acb7c272a5cfd06b57729c460241ee38705049"}, - {file = "chardet-7.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6cdbe9404534cda0d28f172e91fa50db7655ae6262d093b0337a5aa47a47a5f6"}, - {file = "chardet-7.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:427d091994456cc16dbd1e20ae73fee068b9a31f3c90b75072f722d5dbbf156f"}, - {file = "chardet-7.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cad2cd094dfb14cfcb86b0a77568d23375b0005ea0144a726910df6f5c8a46b8"}, - {file = "chardet-7.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23e6acd1a58050d7c2aeecca700c0cf27b5ec4f6153a82c3b51c31b94c6ebfad"}, - {file = "chardet-7.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc5d034faa5b4a2a3af54e24881b2caef9b41fea00a4dddccf97a1e8ec51a213"}, - {file = "chardet-7.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:719c572c4751c201f42134bd2aa0826928ed5113d29dfa482338c1a89bb925fa"}, - {file = "chardet-7.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:13a94d2c0dace263b8dcb61593c165d5749d60e2e2314231938eb87755c9de9f"}, - {file = "chardet-7.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1f081a0f3fce8e1c8f5d6b3691a4960aacc33f213f77ef8b89a6b5f0af4cadf"}, - {file = "chardet-7.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b56152a17d19249388ae99a85a31c35bb8d5b421b90581226de34b2b316be806"}, - {file = "chardet-7.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:7077dc2435b95163db4206aa71ebc329da5bcddb8bfce69440ff8ecf637400bf"}, - {file = "chardet-7.2.0-py3-none-any.whl", hash = "sha256:f8ea866b9fbd8df5f19032d765a4d81dcbf6194a3c7388b44d378d02c9784170"}, - {file = "chardet-7.2.0.tar.gz", hash = "sha256:4ef7292b1342ea805c32cce58a45db204f59d080ed311d6cdaa7ca747fcc0cd5"}, -] - [[package]] name = "charset-normalizer" version = "3.4.6" @@ -824,6 +817,17 @@ files = [ {file = "decorator-5.3.1.tar.gz", hash = "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82"}, ] +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "dill" version = "0.4.1" @@ -988,6 +992,20 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] +[[package]] +name = "fastjsonschema" +version = "2.22.2" +description = "Fastest Python implementation of JSON schema" +optional = false +python-versions = ">=3.10" +files = [ + {file = "fastjsonschema-2.22.2-py3-none-any.whl", hash = "sha256:0fb3915616adac85ccfdd737d26be1089845d2019819505b42d39888458f74d4"}, + {file = "fastjsonschema-2.22.2.tar.gz", hash = "sha256:72064e12356a7d6ef02165be2946b9abadbdf238536e07eb587e3dbaa33099cf"}, +] + +[package.extras] +devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + [[package]] name = "filelock" version = "3.25.2" @@ -1308,6 +1326,41 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jsonschema" +version = "4.26.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.10" +files = [ + {file = "jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}, + {file = "jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.25.0" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.9" +files = [ + {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, + {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + [[package]] name = "jupyter-client" version = "8.10.0" @@ -1351,6 +1404,17 @@ traitlets = ">=5.3" docs = ["intersphinx-registry", "myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest (<9)", "pytest-cov", "pytest-timeout"] +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +description = "Pygments theme using JupyterLab CSS variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, +] + [[package]] name = "kiwisolver" version = "1.5.0" @@ -1910,6 +1974,20 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "mistune" +version = "3.3.4" +description = "A sane and fast Markdown parser with useful plugins and renderers" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mistune-3.3.4-py3-none-any.whl", hash = "sha256:ee015381e955e370962968befe1d729ab60fafb6a715ac6751763fbce38c8d4a"}, + {file = "mistune-3.3.4.tar.gz", hash = "sha256:58b5c96d6fcb61190dfe5fae498d2b2065f99cf61e9649418fd54cf1ada86dfe"}, +] + +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.11\""} + [[package]] name = "mypy-extensions" version = "1.1.0" @@ -1947,6 +2025,85 @@ rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-bo testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pygments (<2.19)", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"] testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"] +[[package]] +name = "nbclient" +version = "0.11.0" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +optional = false +python-versions = ">=3.10.0" +files = [ + {file = "nbclient-0.11.0-py3-none-any.whl", hash = "sha256:ef7fa0d59d6e1d41103933d8a445a18d5de860ca6b613b87b8574accdb3c2895"}, + {file = "nbclient-0.11.0.tar.gz", hash = "sha256:04a134a5b087f2c5887f228aca155db50169b8cd9334dee6942c8e927e56081a"}, +] + +[package.dependencies] +jupyter-client = ">=7.0.0" +jupyter-core = ">=5.4.0" +nbformat = ">=5.2.0" +traitlets = ">=5.13" + +[package.extras] +dev = ["pre-commit"] +docs = ["autodoc-traits", "flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "mock", "moto", "myst-parser", "nbconvert (>=7.1.0)", "pytest (>=9.0.1,<10)", "pytest-asyncio (>=1.3.0)", "pytest-cov (>=4.0)", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling", "testpath", "xmltodict"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.1.0)", "pytest (>=9.0.1,<10)", "pytest-asyncio (>=1.3.0)", "pytest-cov (>=4.0)", "testpath", "xmltodict"] + +[[package]] +name = "nbconvert" +version = "7.17.1" +description = "Convert Jupyter Notebooks (.ipynb files) to other formats." +optional = false +python-versions = ">=3.9" +files = [ + {file = "nbconvert-7.17.1-py3-none-any.whl", hash = "sha256:aa85c087b435e7bf1ffd03319f658e285f2b89eccab33bc1ba7025495ab3e7c8"}, + {file = "nbconvert-7.17.1.tar.gz", hash = "sha256:34d0d0a7e73ce3cbab6c5aae8f4f468797280b01fd8bd2ca746da8569eddd7d2"}, +] + +[package.dependencies] +beautifulsoup4 = "*" +bleach = {version = "!=5.0.0", extras = ["css"]} +defusedxml = "*" +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<4" +nbclient = ">=0.5.0" +nbformat = ">=5.7" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +traitlets = ">=5.1" + +[package.extras] +all = ["flaky", "intersphinx-registry", "ipykernel", "ipython", "ipywidgets (>=7.5)", "myst-parser", "nbsphinx (>=0.2.12)", "playwright", "pydata-sphinx-theme", "pyqtwebengine (>=5.15)", "pytest (>=7)", "sphinx (>=5.0.2)", "sphinxcontrib-spelling", "tornado (>=6.1)"] +docs = ["intersphinx-registry", "ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (>=5.0.2)", "sphinxcontrib-spelling"] +qtpdf = ["pyqtwebengine (>=5.15)"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest (>=7)"] +webpdf = ["playwright"] + +[[package]] +name = "nbformat" +version = "5.11.1" +description = "The Jupyter Notebook format" +optional = false +python-versions = ">=3.10" +files = [ + {file = "nbformat-5.11.1-py3-none-any.whl", hash = "sha256:cc6698fa75f4fab8755ead786317815f13a6fee3b53311c0abb1a8b51d52f7ec"}, + {file = "nbformat-5.11.1.tar.gz", hash = "sha256:32d4521c68c6e7d5b29c76defaeed9f42ea733142b9b19f88277ce10390b9c4d"}, +] + +[package.dependencies] +fastjsonschema = ">=2.15" +jsonschema = ">=2.6" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +traitlets = ">=5.1" + +[package.extras] +docs = ["intersphinx-registry", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["packaging", "pre-commit", "pytest", "testpath"] + [[package]] name = "nest-asyncio2" version = "1.7.2" @@ -2038,13 +2195,13 @@ et-xmlfile = "*" [[package]] name = "packaging" -version = "24.1" +version = "26.3" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c"}, + {file = "packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79"}, ] [[package]] @@ -2146,6 +2303,17 @@ sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-d test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.9.2)"] +[[package]] +name = "pandocfilters" +version = "1.5.1" +description = "Utilities for writing pandoc filters in python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, + {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, +] + [[package]] name = "parso" version = "0.8.7" @@ -2599,22 +2767,18 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pyproject-api" -version = "1.8.0" +version = "1.11.2" description = "API to interact with the python pyproject.toml based projects" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228"}, - {file = "pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496"}, + {file = "pyproject_api-1.11.2-py3-none-any.whl", hash = "sha256:69040bb421a3d502217bf9d5f92a94e65e1db3fe25b641d6064b2b5b9880428b"}, + {file = "pyproject_api-1.11.2.tar.gz", hash = "sha256:7bff8690a101f5f0bac3221475d214018f196ae5eea3af9c9879f4d682a3fd60"}, ] [package.dependencies] -packaging = ">=24.1" -tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=2.4.1)"] -testing = ["covdefaults (>=2.3)", "pytest (>=8.3.3)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] +packaging = ">=25" +tomli = {version = ">=2.3", markers = "python_version < \"3.11\""} [[package]] name = "pyreadline3" @@ -2669,22 +2833,17 @@ six = ">=1.5" [[package]] name = "python-discovery" -version = "1.2.0" +version = "1.6.1" description = "Python interpreter discovery" optional = false python-versions = ">=3.8" files = [ - {file = "python_discovery-1.2.0-py3-none-any.whl", hash = "sha256:1e108f1bbe2ed0ef089823d28805d5ad32be8e734b86a5f212bf89b71c266e4a"}, - {file = "python_discovery-1.2.0.tar.gz", hash = "sha256:7d33e350704818b09e3da2bd419d37e21e7c30db6e0977bb438916e06b41b5b1"}, + {file = "python_discovery-1.6.1-py3-none-any.whl", hash = "sha256:d43fcdef879fe795352bd13ccf8d185ba5a9f86f36cfcd00529f596e737442b3"}, + {file = "python_discovery-1.6.1.tar.gz", hash = "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e"}, ] [package.dependencies] filelock = ">=3.15.4" -platformdirs = ">=4.3.6,<5" - -[package.extras] -docs = ["furo (>=2025.12.19)", "sphinx (>=9.1)", "sphinx-autodoc-typehints (>=3.6.3)", "sphinxcontrib-mermaid (>=2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.5.4)", "pytest (>=8.3.5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] [[package]] name = "python-dotenv" @@ -2938,6 +3097,22 @@ files = [ [package.dependencies] cffi = {version = "*", markers = "implementation_name == \"pypy\""} +[[package]] +name = "referencing" +version = "0.37.0" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.10" +files = [ + {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, + {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" +typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} + [[package]] name = "requests" version = "2.32.5" @@ -2959,6 +3134,130 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "rpds-py" +version = "0.30.0" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.10" +files = [ + {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, + {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7"}, + {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff"}, + {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7"}, + {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139"}, + {file = "rpds_py-0.30.0-cp310-cp310-win32.whl", hash = "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464"}, + {file = "rpds_py-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169"}, + {file = "rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425"}, + {file = "rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85"}, + {file = "rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c"}, + {file = "rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825"}, + {file = "rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229"}, + {file = "rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad"}, + {file = "rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394"}, + {file = "rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf"}, + {file = "rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b"}, + {file = "rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e"}, + {file = "rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2"}, + {file = "rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d"}, + {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7"}, + {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31"}, + {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95"}, + {file = "rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d"}, + {file = "rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15"}, + {file = "rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1"}, + {file = "rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a"}, + {file = "rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0"}, + {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94"}, + {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08"}, + {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27"}, + {file = "rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6"}, + {file = "rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d"}, + {file = "rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0"}, + {file = "rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f"}, + {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65"}, + {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f"}, + {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53"}, + {file = "rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed"}, + {file = "rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950"}, + {file = "rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6"}, + {file = "rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb"}, + {file = "rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5"}, + {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404"}, + {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856"}, + {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40"}, + {file = "rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0"}, + {file = "rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e"}, + {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, +] + [[package]] name = "six" version = "1.17.0" @@ -3379,6 +3678,24 @@ files = [ {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, ] +[[package]] +name = "tinycss2" +version = "1.5.1" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.10" +files = [ + {file = "tinycss2-1.5.1-py3-none-any.whl", hash = "sha256:3415ba0f5839c062696996998176c4a3751d18b7edaaeeb658c9ce21ec150661"}, + {file = "tinycss2-1.5.1.tar.gz", hash = "sha256:d339d2b616ba90ccce58da8495a78f46e55d4d25f9fd71dfd526f07e7d53f957"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["furo", "sphinx"] +test = ["pytest", "ruff"] + [[package]] name = "toml" version = "0.10.2" @@ -3446,6 +3763,17 @@ files = [ {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, ] +[[package]] +name = "tomli-w" +version = "1.2.0" +description = "A lil' TOML writer" +optional = false +python-versions = ">=3.9" +files = [ + {file = "tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90"}, + {file = "tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021"}, +] + [[package]] name = "tomlkit" version = "0.14.0" @@ -3478,30 +3806,32 @@ files = [ [[package]] name = "tox" -version = "4.23.2" +version = "4.61.5" description = "tox is a generic virtualenv management and test command line tool" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "tox-4.23.2-py3-none-any.whl", hash = "sha256:452bc32bb031f2282881a2118923176445bac783ab97c874b8770ab4c3b76c38"}, - {file = "tox-4.23.2.tar.gz", hash = "sha256:86075e00e555df6e82e74cfc333917f91ecb47ffbc868dcafbd2672e332f4a2c"}, + {file = "tox-4.61.5-py3-none-any.whl", hash = "sha256:5f9b109fa0a60b7ccb812e8dacbcf7a06b9a633fa90ae97198334b3464b2f133"}, + {file = "tox-4.61.5.tar.gz", hash = "sha256:d1f535a6ca4827c087e0a2a173dd74621d6e1688c740c8dd44e0377480020431"}, ] [package.dependencies] -cachetools = ">=5.5" -chardet = ">=5.2" +cachetools = ">=7.0.3" colorama = ">=0.4.6" -filelock = ">=3.16.1" -packaging = ">=24.1" -platformdirs = ">=4.3.6" -pluggy = ">=1.5" -pyproject-api = ">=1.8" -tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.12.2", markers = "python_version < \"3.11\""} -virtualenv = ">=20.26.6" +filelock = ">=3.25" +packaging = ">=26" +platformdirs = ">=4.9.4" +pluggy = ">=1.6" +pyproject-api = ">=1.10" +python-discovery = ">=1.4.4" +tomli = {version = ">=2.4", markers = "python_version < \"3.11\""} +tomli-w = ">=1.2" +typing-extensions = {version = ">=4.15", markers = "python_version < \"3.13\""} +virtualenv = ">=21.1" [package.extras] -test = ["devpi-process (>=1.0.2)", "pytest (>=8.3.3)", "pytest-mock (>=3.14)"] +completion = ["argcomplete (>=3.6.3)"] +testing = ["devpi-process (>=1.1.1)", "pytest (>=9.0.2)", "pytest-mock (>=3.15.1)"] [[package]] name = "tqdm" @@ -3605,20 +3935,20 @@ zstd = ["backports-zstd (>=1.0.0)"] [[package]] name = "virtualenv" -version = "21.2.0" +version = "21.7.14" description = "Virtual Python Environment builder" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "virtualenv-21.2.0-py3-none-any.whl", hash = "sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f"}, - {file = "virtualenv-21.2.0.tar.gz", hash = "sha256:1720dc3a62ef5b443092e3f499228599045d7fea4c79199770499df8becf9098"}, + {file = "virtualenv-21.7.14-py3-none-any.whl", hash = "sha256:ac2b2b3755da16aed6302de00ecd0cc43ecc0f295c3f84c064969cd70869ba05"}, + {file = "virtualenv-21.7.14.tar.gz", hash = "sha256:6f14bcaeb6c3438cd8c8cf3ab1805973592fb900e9b724427d1102aaa3db7fbb"}, ] [package.dependencies] distlib = ">=0.3.7,<1" filelock = {version = ">=3.24.2,<4", markers = "python_version >= \"3.10\""} platformdirs = ">=3.9.1,<5" -python-discovery = ">=1" +python-discovery = ">=1.6" typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} [[package]] @@ -3632,6 +3962,21 @@ files = [ {file = "wcwidth-0.8.3.tar.gz", hash = "sha256:d128512515fbf4612e0ff21fd6380399210318b7b54a9af59dff8454cf9730eb"}, ] +[[package]] +name = "webencodings" +version = "0.6.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = ">=3.10" +files = [ + {file = "webencodings-0.6.1-py3-none-any.whl", hash = "sha256:7fab6269c8bf237c657876b52058ccb182e861518d1c695c1a9aaa8c1c105d5b"}, + {file = "webencodings-0.6.1.tar.gz", hash = "sha256:565f9ad031c702dae404e27a099e3e09186a3ab1b9520f06d215502b651fd910"}, +] + +[package.extras] +doc = ["furo", "sphinx"] +test = ["pytest", "ruff"] + [[package]] name = "wrapt" version = "2.1.2" @@ -3737,4 +4082,4 @@ dev = ["pytest", "setuptools"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "d9b3b38c59097c8cc941a2f070514d01c484da045172bfb80c9a5a548686f050" +content-hash = "5579fddf9da46571e370590cc36c8ff3762c83f9eb7cd020471fde6a111b2b5d" diff --git a/pyproject.toml b/pyproject.toml index d6efbe88..2dac8621 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ biofilter = "biofilter.api.cli.main:main" [tool.poetry.dependencies] python = "^3.10" click = "8.1.7" -packaging = "24.1" +packaging = ">=24.1" colorama = "^0.4.6" tqdm = "^4.67.1" sqlalchemy = "^2.0.37" @@ -36,7 +36,7 @@ coverage = "^7.6.8" pytest = "^8.3.4" sphinx = "^8.1.3" sphinx-rtd-theme = "^3.0.2" -tox = "^4.23.2" +tox = "^4.61.5" sphinx-material = "^0.0.36" pylint = "^3.3.3" myst-parser = "^4.0.1" @@ -44,10 +44,11 @@ linkify-it-py = "^2.0.3" testcontainers = "^4.14.1" sphinxcontrib-mermaid = "^2.0.1" ipykernel = "^7.3.0" +nbconvert = "^7.17.1" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.tox] -envlist = "py310,py311,py312" +envlist = "py310,py311,py312,py313" diff --git a/tox.ini b/tox.ini index aa488c79..8175ba0b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,27 +1,27 @@ [tox] -envlist = py310, py311, py312 +envlist = py310, py311, py312, py313 -# Define the test environment for each Python version -# Replace the path with the path to your Python version -# You can find the path to your Python version by running `which python` +# tox builds the package with poetry-core and installs it together with the +# runtime dependencies resolved from pyproject.toml, so the envs only need the +# test-only extras on top. Do not add `poetry install` back here: it is +# redundant, and poetry sharing an env with the package under test makes the +# two compete over common dependencies such as `packaging`. + +[testenv] +deps = pytest +commands = pytest {posargs:tests/} + +# basepython is pinned per interpreter because the 3.10-3.12 builds come from +# pyenv and 3.13 from Homebrew; adjust the paths for your own machine. [testenv:py310] basepython = /Users/andrerico/.pyenv/versions/3.10.3/bin/python -deps = poetry -commands = - poetry install --no-root - pytest tests/ [testenv:py311] basepython = /Users/andrerico/.pyenv/versions/3.11.9/bin/python -deps = poetry -commands = - poetry install --no-root - pytest tests/ [testenv:py312] basepython = /Users/andrerico/.pyenv/versions/3.12.3/bin/python -deps = poetry -commands = - poetry install --no-root - pytest tests/ + +[testenv:py313] +basepython = /opt/homebrew/bin/python3.13 From 50ec4967edd5b6c7cff5d96970bc0fc586ec40a6 Mon Sep 17 00:00:00 2001 From: Andre Date: Fri, 18 Sep 2026 17:11:47 -0400 Subject: [PATCH 2/4] chore: clear the last biofilter_430 paths, and re-sync the assistant kit Renaming the project directory left the package installed editable against the old path: biofilter.pth still read biofilter_430, so `import biofilter` only resolved by accident of pytest.ini's `pythonpath = .` and the working directory. Rebuilding the venv fixes that, but two tracked files carried the old path too. reports__annotate_gene.ipynb was the one template with an absolute bundle path, pointing into a directory that is going away. Every other template uses `BUNDLE = None` and falls back to the bundle in .biofilter.toml, so it does that now as well. bf4_notebooks.md is generated from those templates, so regenerating the kit picks the fix up. It also catches the consolidated files up with changes already committed but never re-synced: seventeen reports rather than sixteen, pair_genes alongside pair_variants, and the Docker image renamed to ghcr.io/ritchielab/biofilter. Co-Authored-By: Claude Opus 5 (1M context) --- assistent/gpt_builder/consolidated/bf4_agents.md | 9 +++++---- assistent/gpt_builder/consolidated/bf4_docs.md | 16 ++++++++-------- assistent/gpt_builder/consolidated/bf4_faq.md | 9 +++++---- .../gpt_builder/consolidated/bf4_notebooks.md | 6 +++--- notebooks/templates/reports__annotate_gene.ipynb | 4 ++-- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/assistent/gpt_builder/consolidated/bf4_agents.md b/assistent/gpt_builder/consolidated/bf4_agents.md index ce5c5f55..b16f05e5 100644 --- a/assistent/gpt_builder/consolidated/bf4_agents.md +++ b/assistent/gpt_builder/consolidated/bf4_agents.md @@ -170,7 +170,7 @@ one; the wrapper is what carries `.provenance`, `.num_rows` and `.columns`. ## 8) The reports -Sixteen, in six families. `biofilter report list --verbose` is always the +Seventeen, in six families. `biofilter report list --verbose` is always the authority for what your install has. | Family | Reports | @@ -178,7 +178,7 @@ authority for what your install has. | `annotate_*` | `annotate_gene`, `annotate_variant`, `annotate_protein`, `annotate_disease`, `annotate_pathway`, `annotate_go` | | `expand_*` | `expand_gene_to_variant`, `expand_variant_regulatory`, `expand_entity_neighborhood`, `expand_entity_relationship` | | `resolve_*` | `resolve_entity` | -| `pair_*` | `pair_variants` | +| `pair_*` | `pair_genes`, `pair_variants` | | `aggregate_*` | `aggregate_cohort_variants` | | `platform_*` | `platform_data_statistics`, `platform_etl_status`, `platform_etl_packages` | @@ -191,6 +191,7 @@ By the question instead: | rsIDs or positions | `annotate_variant` | | genes, want the variants in them | `expand_gene_to_variant` | | variants, want what they regulate | `expand_variant_regulatory` | +| genes, want pairs that share biology | `pair_genes` | | variants, want candidate pairs | `pair_variants` | | a cohort | `aggregate_cohort_variants` | | a bundle you do not know | `platform_data_statistics` | @@ -353,7 +354,7 @@ docker run --rm \ -v /path/to/bundles/20260914:/bundle:ro \ -v "$PWD/out:/workspace" \ --user "$(id -u):$(id -g)" \ - ricoandre/biofilter:latest \ + ghcr.io/ritchielab/biofilter:latest \ report run --report-name annotate_gene --input TP53 --output /workspace/genes.csv ``` @@ -361,7 +362,7 @@ Under Apptainer, `--bind` replaces `-v` and output ownership takes care of itself: ```bash -apptainer pull bf4.sif docker://ghcr.io/ritchielab/biofilter-hpc:latest +apptainer pull bf4.sif docker://ghcr.io/ritchielab/biofilter:latest ``` ### 3.3 Option C - Source diff --git a/assistent/gpt_builder/consolidated/bf4_docs.md b/assistent/gpt_builder/consolidated/bf4_docs.md index ac9b6806..facd99f3 100644 --- a/assistent/gpt_builder/consolidated/bf4_docs.md +++ b/assistent/gpt_builder/consolidated/bf4_docs.md @@ -475,10 +475,10 @@ python -c "from biofilter import Biofilter; print('OK')" ## Docker -One image, published to two registries. Pull it rather than building: +One image, for Docker and Apptainer alike. Pull it rather than building: ```bash -docker pull ricoandre/biofilter:latest +docker pull ghcr.io/ritchielab/biofilter:latest ``` The image carries no data. It expects two mounts: @@ -496,7 +496,7 @@ docker run --rm \ -v /shared/bundles/20260914:/bundle:ro \ -v "$(pwd)/out:/workspace" \ --user "$(id -u):$(id -g)" \ - ricoandre/biofilter:latest \ + ghcr.io/ritchielab/biofilter:latest \ report run --report-name annotate_gene --input TP53 --output /workspace/genes.csv ``` @@ -515,7 +515,7 @@ docker run --rm -it \ -v /shared/bundles/20260914:/bundle:ro \ -v "$(pwd):/workspace" \ --entrypoint /bin/bash \ - ricoandre/biofilter:latest + ghcr.io/ritchielab/biofilter:latest ``` To build it yourself from a checkout: @@ -530,7 +530,7 @@ The same image. `--bind` replaces `-v`, and output ownership takes care of itself because the container runs as you: ```bash -apptainer pull bf4.sif docker://ghcr.io/ritchielab/biofilter-hpc:latest +apptainer pull bf4.sif docker://ghcr.io/ritchielab/biofilter:latest apptainer run \ --bind /shared/bundles/20260914:/bundle:ro \ @@ -539,8 +539,8 @@ apptainer run \ report run --report-name annotate_gene --input APOE --output /workspace/apoe.csv ``` -The GHCR name `biofilter-hpc` predates the merge of what used to be two -images; it is the same image as Docker Hub's. +It is the same image either way — what changes is `--bind` in place of +`-v`, and that Apptainer runs the container as you. ## From source @@ -2323,7 +2323,7 @@ to that path, or the file leaves with the container: docker run --rm \ -v /shared/bundles/20260914:/bundle:ro \ -v "$(pwd)/out:/workspace" \ - ricoandre/biofilter:latest \ + ghcr.io/ritchielab/biofilter:latest \ report run --report-name platform_etl_status --output /workspace/etl_status.csv ``` diff --git a/assistent/gpt_builder/consolidated/bf4_faq.md b/assistent/gpt_builder/consolidated/bf4_faq.md index a203d563..26381a02 100644 --- a/assistent/gpt_builder/consolidated/bf4_faq.md +++ b/assistent/gpt_builder/consolidated/bf4_faq.md @@ -36,7 +36,7 @@ provenance inside the file. biofilter report list --verbose ``` -Sixteen, in six families. By the shape of the question: +Seventeen, in six families. By the shape of the question: | You have | Report | |---|---| @@ -53,6 +53,7 @@ Sixteen, in six families. By the shape of the question: | a gene-to-anything list of your own, want the pairs it implies | `pair_genes` | | a cohort | `aggregate_cohort_variants` | | a bundle you do not know | `platform_data_statistics` | +| to know what ran to build it | `platform_etl_status`, and `platform_etl_packages` for the raw record | ### A2b) `pair_variants` or `pair_genes`? @@ -399,7 +400,7 @@ docker run --rm \ -v /path/to/bundles/20260914:/bundle:ro \ -v "$PWD/out:/workspace" \ --user "$(id -u):$(id -g)" \ - ricoandre/biofilter:latest \ + ghcr.io/ritchielab/biofilter:latest \ report run --report-name annotate_gene --input TP53 --output /workspace/genes.csv ``` @@ -419,7 +420,7 @@ container runs as you. ### D4) Apptainer / Singularity ```bash -apptainer pull bf4.sif docker://ghcr.io/ritchielab/biofilter-hpc:latest +apptainer pull bf4.sif docker://ghcr.io/ritchielab/biofilter:latest apptainer run \ --bind /path/to/bundles/20260914:/bundle:ro \ @@ -428,7 +429,7 @@ apptainer run \ report run --report-name annotate_gene --input APOE --output /workspace/apoe.csv ``` -Same image as Docker Hub; the `-hpc` name is historical. +The same image as the Docker example above; only the mount flag differs. --- diff --git a/assistent/gpt_builder/consolidated/bf4_notebooks.md b/assistent/gpt_builder/consolidated/bf4_notebooks.md index 4871f09d..2af7c118 100644 --- a/assistent/gpt_builder/consolidated/bf4_notebooks.md +++ b/assistent/gpt_builder/consolidated/bf4_notebooks.md @@ -185,7 +185,7 @@ missing source or a version mismatch are printed, not raised. If you prefer a container to the module: ```bash -apptainer pull bf4.sif docker://ghcr.io/ritchielab/biofilter-hpc:latest +apptainer pull bf4.sif docker://ghcr.io/ritchielab/biofilter:latest apptainer run \ --bind /project/hall_shared/datasets/biofilter/:/bundle:ro \ @@ -1139,10 +1139,10 @@ from pathlib import Path from biofilter import Biofilter -BUNDLE = "/Users/andrerico/Works/Sys/biofilter_430/biofilter_data/bundles/20260914" # change this to the path of your biofilter_data bundle +BUNDLE = None # set a path to override; None reads [database] bundle from .biofilter.toml REPORT = "annotate_gene" -bf = Biofilter(bundle=BUNDLE, debug_mode=False) +bf = Biofilter(bundle=BUNDLE, debug_mode=False) if BUNDLE else Biofilter(debug_mode=False) # Results land here whatever directory the kernel was started in — VS Code # and Jupyter disagree about that, and a bare filename ends up wherever diff --git a/notebooks/templates/reports__annotate_gene.ipynb b/notebooks/templates/reports__annotate_gene.ipynb index 2bc3e5e2..e1b1f9fd 100644 --- a/notebooks/templates/reports__annotate_gene.ipynb +++ b/notebooks/templates/reports__annotate_gene.ipynb @@ -63,10 +63,10 @@ "\n", "from biofilter import Biofilter\n", "\n", - "BUNDLE = \"/Users/andrerico/Works/Sys/biofilter_430/biofilter_data/bundles/20260914\" # change this to the path of your biofilter_data bundle\n", + "BUNDLE = None # set a path to override; None reads [database] bundle from .biofilter.toml\n", "REPORT = \"annotate_gene\"\n", "\n", - "bf = Biofilter(bundle=BUNDLE, debug_mode=False)\n", + "bf = Biofilter(bundle=BUNDLE, debug_mode=False) if BUNDLE else Biofilter(debug_mode=False)\n", "\n", "# Results land here whatever directory the kernel was started in \u2014 VS Code\n", "# and Jupyter disagree about that, and a bare filename ends up wherever\n", From b2bb30086a38fc69d24eb14425b60d4fe4780d8c Mon Sep 17 00:00:00 2001 From: Andre Date: Fri, 18 Sep 2026 17:11:50 -0400 Subject: [PATCH 3/4] chore(coverage): stop omitting directories that no longer exist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit biofilter/alembic and modules/report/reports_bkp are both gone — the schema is built with create_all rather than migrations, and every report was rewritten against the bundle. Omitting them measures nothing. Co-Authored-By: Claude Opus 5 (1M context) --- .coveragerc-core | 2 -- 1 file changed, 2 deletions(-) diff --git a/.coveragerc-core b/.coveragerc-core index 00f5e75f..b36c0af2 100644 --- a/.coveragerc-core +++ b/.coveragerc-core @@ -3,9 +3,7 @@ branch = True source = biofilter omit = */tests/* - */biofilter/alembic/* */biofilter/modules/etl/dtps/* - */biofilter/modules/report/reports_bkp/* [report] show_missing = True From 358bfc01aa60d3f8925c0149d696db31d734333b Mon Sep 17 00:00:00 2001 From: Andre Date: Fri, 18 Sep 2026 17:14:10 -0400 Subject: [PATCH 4/4] readme --- README.md | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 580d723a..a42ebcc5 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ A **bundle**: a dated directory of Parquet files with a `manifest.json` describing them. ``` -20260914/ +bundle/ ├── manifest.json the catalogue: every file, its rows, its size ├── bundle_plan.json which sources went in, at which versions ├── build_record.json what each build run did, in order @@ -87,13 +87,13 @@ for the disk, time and memory it takes. Biofilter has two halves, separated by the bundle rather than by an API. -| | Builds a bundle | Reads a bundle | -|---|---|---| -| Who | whoever maintains the data | everyone else | -| How often | a few times a year | constantly | -| Engine | SQLAlchemy models, staging SQLite | DuckDB, in process | -| Can write | yes — it is the only code that can | no, structurally | -| Commands | `bundle`, `etl`, `db` | `report` | +| | Builds a bundle | Reads a bundle | +| --------- | ---------------------------------- | ------------------ | +| Who | whoever maintains the data | everyone else | +| How often | a few times a year | constantly | +| Engine | SQLAlchemy models, staging SQLite | DuckDB, in process | +| Can write | yes — it is the only code that can | no, structurally | +| Commands | `bundle`, `etl`, `db` | `report` | The build runs in **two branches**. The core — genes, proteins, pathways, diseases, GO, chemicals and their relationships — is about 7 million rows and @@ -103,7 +103,7 @@ no foreign keys, so there is nothing to resolve and nothing to stage: it writes its final Parquet directly. 📖 [System Overview](https://biofilter.readthedocs.io/en/latest/technical/system_overview.html) - · [The Read Path](https://biofilter.readthedocs.io/en/latest/technical/read_path.html) +· [The Read Path](https://biofilter.readthedocs.io/en/latest/technical/read_path.html) --- @@ -112,14 +112,14 @@ its final Parquet directly. A report takes a list of things you have and returns a table. Seventeen of them, in six families: -| Family | What they answer | -|---|---| -| `resolve_*` | Which of my names does Biofilter recognise? | -| `annotate_*` | What is known about these genes, variants, proteins, pathways, diseases, GO terms? | -| `expand_*` | What is connected to them — neighbours, relationships, variants in a gene, regulatory evidence? | -| `pair_*` | Which of these genes or variants share biology, and on what support? | -| `aggregate_*` | Roll a cohort's variants up to a summary. | -| `platform_*` | What does this bundle contain, and how was it built? | +| Family | What they answer | +| ------------- | ----------------------------------------------------------------------------------------------- | +| `resolve_*` | Which of my names does Biofilter recognise? | +| `annotate_*` | What is known about these genes, variants, proteins, pathways, diseases, GO terms? | +| `expand_*` | What is connected to them — neighbours, relationships, variants in a gene, regulatory evidence? | +| `pair_*` | Which of these genes or variants share biology, and on what support? | +| `aggregate_*` | Roll a cohort's variants up to a summary. | +| `platform_*` | What does this bundle contain, and how was it built? | ```bash biofilter report list --verbose @@ -133,14 +133,14 @@ biofilter report explain --report-name expand_gene_to_variant One per report, runnable against a bundle: -| | | -|---|---| -| [`reports__101`](notebooks/templates/reports__101.ipynb) | **start here** — how reports work | -| [`reports__resolve_entity`](notebooks/templates/reports__resolve_entity.ipynb) | start here for a new input list | -| [`reports__annotate_gene`](notebooks/templates/reports__annotate_gene.ipynb) | annotating a gene list | -| [`reports__expand_gene_to_variant`](notebooks/templates/reports__expand_gene_to_variant.ipynb) | variants in a gene, filtered by predicted damage | -| [`reports__aggregate_cohort_variants`](notebooks/templates/reports__aggregate_cohort_variants.ipynb) | a cohort, matched and binned | -| [`reports__TEMPLATE`](notebooks/templates/reports__TEMPLATE.ipynb) | copy this to write a new report | +| | | +| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------ | +| [`reports__101`](notebooks/templates/reports__101.ipynb) | **start here** — how reports work | +| [`reports__resolve_entity`](notebooks/templates/reports__resolve_entity.ipynb) | start here for a new input list | +| [`reports__annotate_gene`](notebooks/templates/reports__annotate_gene.ipynb) | annotating a gene list | +| [`reports__expand_gene_to_variant`](notebooks/templates/reports__expand_gene_to_variant.ipynb) | variants in a gene, filtered by predicted damage | +| [`reports__aggregate_cohort_variants`](notebooks/templates/reports__aggregate_cohort_variants.ipynb) | a cohort, matched and binned | +| [`reports__TEMPLATE`](notebooks/templates/reports__TEMPLATE.ipynb) | copy this to write a new report | All of them: [`notebooks/templates/`](notebooks/templates/) @@ -203,7 +203,7 @@ apptainer run \ `--output` writes inside the container, so it has to point at `/workspace`. 📖 [docker/README.md](docker/README.md) · Penn LPC users: -[lpc__quickstart.md](notebooks/lpc__quickstart.md) +[lpc\_\_quickstart.md](notebooks/lpc__quickstart.md) ---