diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a463a491..d12f9514 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -110,6 +110,33 @@ jobs: if: steps.setup-python.outputs.cache-hit != 'true' run: poetry install --no-interaction --no-root --no-ansi + # Build docker container needed for test + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Cache Template Testing Containers + uses: actions/cache@v3 + with: + path: container-test-template-cache + key: ${{ runner.os }}-test-template-cache-${{ hashFiles('containers/test-template/**') }}-${{ steps.setup-python.outputs.python-version }} + - name: Inject container-test-template-cache into docker + uses: reproducible-containers/buildkit-cache-dance@v2.1.2 + with: + cache-source: container-test-template-cache + - name: Build Docker container for cache + uses: docker/build-push-action@v5 + with: + context: containers/test-template + cache-from: type=gha + cache-to: type=gha,mode=max + push: false + load: false + tags: snakebids/test-template:${{ steps.setup-python.outputs.python-version }} + platforms: linux/amd64 + build-args: | + PYTHON_VERSION=${{ steps.setup-python.outputs.python-version }} + test: runs-on: ubuntu-latest needs: [ 'build-cache-env' ] @@ -153,6 +180,35 @@ jobs: - name: Install dependencies if: steps.setup-python.outputs.cache-hit != 'true' run: poetry install --no-interaction --no-root --no-ansi + + + # Build docker container needed for test + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Cache Template Testing Containers + uses: actions/cache@v3 + with: + path: container-test-template-cache + key: ${{ runner.os }}-test-template-cache-${{ hashFiles('containers/test-template/**') }}-${{ steps.setup-python.outputs.python-version }} + - name: Inject container-test-template-cache into docker + uses: reproducible-containers/buildkit-cache-dance@v2.1.2 + with: + cache-source: container-test-template-cache + - name: Build Docker container for cache + uses: docker/build-push-action@v5 + with: + context: containers/test-template + cache-from: type=gha + cache-to: type=gha,mode=max + push: false + load: true + tags: snakebids/test-template:${{ steps.setup-python.outputs.python-version }} + platforms: linux/amd64 + build-args: | + PYTHON_VERSION=${{ steps.setup-python.outputs.python-version }} + - name: Install library run: poetry install --no-interaction --no-ansi diff --git a/containers/test-template/Dockerfile b/containers/test-template/Dockerfile new file mode 100644 index 00000000..52372877 --- /dev/null +++ b/containers/test-template/Dockerfile @@ -0,0 +1,21 @@ +ARG PYTHON_VERSION=3.11 +FROM python:${PYTHON_VERSION}-slim + +# Install and uninstall snakebids to cache it and it's dependences +RUN apt-get update && apt-get install -y gcc && \ + rm -rf /var/lib/apt/lists/* && \ + python -m pip install pipx && \ + pipx install poetry && \ + pipx install hatch && \ + pipx install pdm && \ + mkdir prebuild && \ + cd prebuild && \ + pip wheel snakebids && \ + cd .. && \ + rm -rf prebuild + +COPY ./test-template.sh /run/test-template.sh +ENV PATH="/root/.local/bin:$PATH" + +WORKDIR /work +ENTRYPOINT [ "/run/test-template.sh" ] diff --git a/containers/test-template/test-template.sh b/containers/test-template/test-template.sh new file mode 100755 index 00000000..14d44733 --- /dev/null +++ b/containers/test-template/test-template.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -eu + +method="$1" +script_name="$2" + +cp -r /app/* /work +script="'${script_name}' tests/data tests/result participant -c1 --skip-bids-validation" +case "$method" in + "setuptools" ) + python -m venv .venv + .venv/bin/python -m pip install . + PATH=".venv/bin:$PATH" eval "$script" + ;; + "poetry" ) + poetry install + eval "poetry run $script" + ;; + "hatch" ) + hatch env create + eval "hatch env run -- $script" + ;; + "pdm" ) + pdm install + eval "pdm run $script" + ;; + * ) + >&2 echo "Invalid method" + exit 1 + ;; +esac diff --git a/poetry.lock b/poetry.lock index f03ed824..94809e84 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,18 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.7" +files = [ + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} [[package]] name = "appdirs" @@ -67,58 +81,44 @@ files = [ [[package]] name = "bids-validator" -version = "1.12.0" +version = "1.13.1" description = "Validator for the Brain Imaging Data Structure" optional = false python-versions = "*" files = [ - {file = "bids-validator-1.12.0.tar.gz", hash = "sha256:5f9ebd379cdf6d383e983c10539886bf5ea488e4ebf2bc21293125f510893116"}, - {file = "bids_validator-1.12.0-py2.py3-none-any.whl", hash = "sha256:7936e9f31960cfbfe9af49b33e8d10999d7497d7fcd313d91ea3eda541ae4500"}, + {file = "bids-validator-1.13.1.tar.gz", hash = "sha256:7205ce4e68fba172215332c786f1ac1665025b702b6dff2b1e158f00a2df9890"}, + {file = "bids_validator-1.13.1-py2.py3-none-any.whl", hash = "sha256:da6edf5e76ef86c8a63b3fcee1dbfb039a16a9ef63cb0d2d05312c200d4607f7"}, ] -[[package]] -name = "binaryornot" -version = "0.4.4" -description = "Ultra-lightweight pure Python package to check if a file is binary or text." -optional = false -python-versions = "*" -files = [ - {file = "binaryornot-0.4.4-py2.py3-none-any.whl", hash = "sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4"}, - {file = "binaryornot-0.4.4.tar.gz", hash = "sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061"}, -] - -[package.dependencies] -chardet = ">=3.0.2" - [[package]] name = "black" -version = "23.7.0" +version = "23.9.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, - {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, - {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, - {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, - {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, - {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, - {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, - {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, - {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, - {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, - {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, - {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, - {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, + {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, + {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, + {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, + {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, + {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, + {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, + {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, + {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, + {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, + {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, ] [package.dependencies] @@ -128,7 +128,7 @@ packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -191,17 +191,6 @@ files = [ {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, ] -[[package]] -name = "chardet" -version = "5.2.0" -description = "Universal encoding detector for Python 3" -optional = false -python-versions = ">=3.7" -files = [ - {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, - {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, -] - [[package]] name = "charset-normalizer" version = "3.2.0" @@ -337,25 +326,32 @@ files = [ ] [[package]] -name = "cookiecutter" -version = "2.3.0" -description = "A command-line utility that creates projects from project templates, e.g. creating a Python package project from a Python package project template." +name = "copier" +version = "8.3.0" +description = "A library for rendering project templates." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8,<4.0" files = [ - {file = "cookiecutter-2.3.0-py3-none-any.whl", hash = "sha256:7e87944757c6e9f8729cf89a4139b6a35ab4d6dcbc6ae3e7d6360d44ad3ad383"}, - {file = "cookiecutter-2.3.0.tar.gz", hash = "sha256:942a794981747f6d7f439d6e49d39dc91a9a641283614160c93c474c72c29621"}, + {file = "copier-8.3.0-py3-none-any.whl", hash = "sha256:a708e9b7c0eb7363ee5935f7a96a63a6f39b6da1d36f1c931d1ebd7711bb2ecf"}, + {file = "copier-8.3.0.tar.gz", hash = "sha256:051149721c811bfa84023fca5c23827917ac5f42ab6c2696dcb522b17aee7cae"}, ] [package.dependencies] -arrow = "*" -binaryornot = ">=0.4.4" -click = ">=7.0,<9.0.0" -Jinja2 = ">=2.7,<4.0.0" -python-slugify = ">=4.0.0" +colorama = ">=0.4.3" +decorator = ">=5.1.1" +dunamai = ">=1.7.0" +funcy = ">=1.17" +jinja2 = ">=3.1.1" +jinja2-ansible-filters = ">=1.3.1" +packaging = ">=23.0" +pathspec = ">=0.9.0" +plumbum = ">=1.6.9" +pydantic = ">=2.0.3" +pygments = ">=2.7.1" pyyaml = ">=5.3.1" -requests = ">=2.23.0" -rich = "*" +pyyaml-include = ">=1.2" +questionary = ">=1.8.1" +typing-extensions = {version = ">=3.7.4,<5.0.0", markers = "python_version < \"3.9\""} [[package]] name = "datrie" @@ -391,6 +387,17 @@ files = [ {file = "datrie-0.8.2.tar.gz", hash = "sha256:525b08f638d5cf6115df6ccd818e5a01298cd230b2dac91c8ff2e6499d18765d"}, ] +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + [[package]] name = "distlib" version = "0.3.7" @@ -434,6 +441,20 @@ files = [ {file = "dpath-2.1.6.tar.gz", hash = "sha256:f1e07c72e8605c6a9e80b64bc8f42714de08a789c7de417e49c3f87a19692e47"}, ] +[[package]] +name = "dunamai" +version = "1.18.1" +description = "Dynamic version generation" +optional = false +python-versions = ">=3.5,<4.0" +files = [ + {file = "dunamai-1.18.1-py3-none-any.whl", hash = "sha256:ee7b042f7a687fa04fc383258eb93bd819c7bd8aec62e0974f3c69747e5958f2"}, + {file = "dunamai-1.18.1.tar.gz", hash = "sha256:5e9a91e43d16bb56fa8fcddcf92fa31b2e1126e060c3dcc8d094d9b508061f9d"}, +] + +[package.dependencies] +packaging = ">=20.9" + [[package]] name = "exceptiongroup" version = "1.1.3" @@ -478,18 +499,19 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "filelock" -version = "3.12.2" +version = "3.12.4" description = "A platform independent file lock." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"}, - {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"}, + {file = "filelock-3.12.4-py3-none-any.whl", hash = "sha256:08c21d87ded6e2b9da6728c3dff51baf1dcecf973b768ef35bcbc3447edb9ad4"}, + {file = "filelock-3.12.4.tar.gz", hash = "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd"}, ] [package.extras] -docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2023.7.26)", "sphinx (>=7.1.2)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3)", "diff-cover (>=7.7)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest-timeout (>=2.1)"] +typing = ["typing-extensions (>=4.7.1)"] [[package]] name = "formulaic" @@ -516,6 +538,17 @@ wrapt = ">=1.0" arrow = ["pyarrow (>=1)"] calculus = ["sympy (>=1.3,<1.10)"] +[[package]] +name = "funcy" +version = "2.0" +description = "A fancy and practical functional tools" +optional = false +python-versions = "*" +files = [ + {file = "funcy-2.0-py2.py3-none-any.whl", hash = "sha256:53df23c8bb1651b12f095df764bfb057935d49537a56de211b098f4c79614bb0"}, + {file = "funcy-2.0.tar.gz", hash = "sha256:3963315d59d41c6f30c04bc910e10ab50a3ac4a225868bfa96feed133df075cb"}, +] + [[package]] name = "gitdb" version = "4.0.10" @@ -532,18 +565,21 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.32" +version = "3.1.37" description = "GitPython is a Python library used to interact with Git repositories" optional = false python-versions = ">=3.7" files = [ - {file = "GitPython-3.1.32-py3-none-any.whl", hash = "sha256:e3d59b1c2c6ebb9dfa7a184daf3b6dd4914237e7488a1730a6d8f6f5d0b4187f"}, - {file = "GitPython-3.1.32.tar.gz", hash = "sha256:8d9b8cb1e80b9735e8717c9362079d3ce4c6e5ddeebedd0361b228c3a67a62f6"}, + {file = "GitPython-3.1.37-py3-none-any.whl", hash = "sha256:5f4c4187de49616d710a77e98ddf17b4782060a1788df441846bddefbb89ab33"}, + {file = "GitPython-3.1.37.tar.gz", hash = "sha256:f9b9ddc0761c125d5780eab2d64be4873fc6817c2899cbcb34b02344bdc7bc54"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" +[package.extras] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar"] + [[package]] name = "graphlib-backport" version = "1.0.3" @@ -644,13 +680,13 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve [[package]] name = "hypothesis" -version = "6.82.6" +version = "6.86.2" description = "A library for property-based testing" optional = false python-versions = ">=3.8" files = [ - {file = "hypothesis-6.82.6-py3-none-any.whl", hash = "sha256:e99c445140e43f1cceda07b569f2f2d920d95435c6b0e6b507b35b01bb025e9d"}, - {file = "hypothesis-6.82.6.tar.gz", hash = "sha256:f52ac4180a16208224e3d648fbf0fef8b9ca24863ba4b41bfef30a78c42646bd"}, + {file = "hypothesis-6.86.2-py3-none-any.whl", hash = "sha256:e1d36522824d62bb3e9fcb7b57dd4a6ca330bb36921324bb19c476bdafabeda7"}, + {file = "hypothesis-6.86.2.tar.gz", hash = "sha256:e5d75d70f5a4fc372cddf03ec6141237a0a270ed106aeb2156a4984f06d37b0f"}, ] [package.dependencies] @@ -676,13 +712,13 @@ zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2023.3)"] [[package]] name = "identify" -version = "2.5.27" +version = "2.5.29" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.27-py2.py3-none-any.whl", hash = "sha256:fdb527b2dfe24602809b2201e033c2a113d7bdf716db3ca8e3243f735dcecaba"}, - {file = "identify-2.5.27.tar.gz", hash = "sha256:287b75b04a0e22d727bc9a41f0d4f3c1bcada97490fa6eabb5b28f0e9097e733"}, + {file = "identify-2.5.29-py2.py3-none-any.whl", hash = "sha256:24437fbf6f4d3fe6efd0eb9d67e24dd9106db99af5ceb27996a5f7895f24bf1b"}, + {file = "identify-2.5.29.tar.gz", hash = "sha256:d43d52b86b15918c137e3a74fff5224f60385cd0e9c38e99d07c257f02f151a5"}, ] [package.extras] @@ -701,21 +737,21 @@ files = [ [[package]] name = "importlib-resources" -version = "6.0.1" +version = "6.1.0" description = "Read resources from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.0.1-py3-none-any.whl", hash = "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf"}, - {file = "importlib_resources-6.0.1.tar.gz", hash = "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4"}, + {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"}, + {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] [[package]] name = "inflect" @@ -828,17 +864,18 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec [[package]] name = "jaraco-functools" -version = "3.8.1" +version = "3.9.0" description = "Functools like those found in stdlib" optional = false python-versions = ">=3.8" files = [ - {file = "jaraco.functools-3.8.1-py3-none-any.whl", hash = "sha256:784718fbc5d70c5a7bd881c362d23d561913102eb1381cec21327c8ebda3351c"}, - {file = "jaraco.functools-3.8.1.tar.gz", hash = "sha256:e96a0d4ea455005a4092ce89a69ea0f7fb7e22807ad3b1008f9bf70c48d1cf2e"}, + {file = "jaraco.functools-3.9.0-py3-none-any.whl", hash = "sha256:df2e2b0aadd2dfcee2d7e0d7d083d5a5b68f4c8621e6915ae9819a90de65dd44"}, + {file = "jaraco.functools-3.9.0.tar.gz", hash = "sha256:8b137b0feacc17fef4bacee04c011c9e86f2341099c870a1d12d3be37b32a638"}, ] [package.dependencies] more-itertools = "*" +typing-extensions = {version = "*", markers = "python_version < \"3.11\""} [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] @@ -941,15 +978,48 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jinja2-ansible-filters" +version = "1.3.2" +description = "A port of Ansible's jinja2 filters without requiring ansible core." +optional = false +python-versions = "*" +files = [ + {file = "jinja2-ansible-filters-1.3.2.tar.gz", hash = "sha256:07c10cf44d7073f4f01102ca12d9a2dc31b41d47e4c61ed92ef6a6d2669b356b"}, + {file = "jinja2_ansible_filters-1.3.2-py3-none-any.whl", hash = "sha256:e1082f5564917649c76fed239117820610516ec10f87735d0338688800a55b34"}, +] + +[package.dependencies] +Jinja2 = "*" +PyYAML = "*" + +[package.extras] +test = ["pytest", "pytest-cov"] + +[[package]] +name = "jinja2-time" +version = "0.2.0" +description = "Jinja2 Extension for Dates and Times" +optional = false +python-versions = "*" +files = [ + {file = "jinja2-time-0.2.0.tar.gz", hash = "sha256:d14eaa4d315e7688daa4969f616f226614350c48730bfa1692d2caebd8c90d40"}, + {file = "jinja2_time-0.2.0-py2.py3-none-any.whl", hash = "sha256:d3eab6605e3ec8b7a0863df09cc1d23714908fa61aa6986a845c20ba488b4efa"}, +] + +[package.dependencies] +arrow = "*" +jinja2 = "*" + [[package]] name = "jsonschema" -version = "4.19.0" +version = "4.19.1" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.19.0-py3-none-any.whl", hash = "sha256:043dc26a3845ff09d20e4420d6012a9c91c9aa8999fa184e7efcfeccb41e32cb"}, - {file = "jsonschema-4.19.0.tar.gz", hash = "sha256:6e1e7569ac13be8139b2dd2c21a55d350066ee3f80df06c608b398cdc6f30e8f"}, + {file = "jsonschema-4.19.1-py3-none-any.whl", hash = "sha256:cd5f1f9ed9444e554b38ba003af06c0a8c2868131e56bfbef0550fb450c0330e"}, + {file = "jsonschema-4.19.1.tar.gz", hash = "sha256:ec84cc37cfa703ef7cd4928db24f9cb31428a5d0fa77747b8b51a847458e0bbf"}, ] [package.dependencies] @@ -999,30 +1069,6 @@ traitlets = ">=5.3" docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - [[package]] name = "markupsafe" version = "2.1.3" @@ -1082,17 +1128,6 @@ files = [ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - [[package]] name = "mkinit" version = "1.0.0" @@ -1292,36 +1327,43 @@ files = [ [[package]] name = "numpy" -version = "1.25.2" +version = "1.26.0" description = "Fundamental package for array computing in Python" optional = false -python-versions = ">=3.9" -files = [ - {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"}, - {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"}, - {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"}, - {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"}, - {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"}, - {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"}, - {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"}, - {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"}, - {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"}, - {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"}, - {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"}, - {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"}, - {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"}, - {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"}, - {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"}, - {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"}, - {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"}, - {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"}, - {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"}, - {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"}, - {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"}, - {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"}, - {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"}, - {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"}, - {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, +python-versions = "<3.13,>=3.9" +files = [ + {file = "numpy-1.26.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8db2f125746e44dce707dd44d4f4efeea8d7e2b43aace3f8d1f235cfa2733dd"}, + {file = "numpy-1.26.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0621f7daf973d34d18b4e4bafb210bbaf1ef5e0100b5fa750bd9cde84c7ac292"}, + {file = "numpy-1.26.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51be5f8c349fdd1a5568e72713a21f518e7d6707bcf8503b528b88d33b57dc68"}, + {file = "numpy-1.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:767254ad364991ccfc4d81b8152912e53e103ec192d1bb4ea6b1f5a7117040be"}, + {file = "numpy-1.26.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:436c8e9a4bdeeee84e3e59614d38c3dbd3235838a877af8c211cfcac8a80b8d3"}, + {file = "numpy-1.26.0-cp310-cp310-win32.whl", hash = "sha256:c2e698cb0c6dda9372ea98a0344245ee65bdc1c9dd939cceed6bb91256837896"}, + {file = "numpy-1.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:09aaee96c2cbdea95de76ecb8a586cb687d281c881f5f17bfc0fb7f5890f6b91"}, + {file = "numpy-1.26.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:637c58b468a69869258b8ae26f4a4c6ff8abffd4a8334c830ffb63e0feefe99a"}, + {file = "numpy-1.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:306545e234503a24fe9ae95ebf84d25cba1fdc27db971aa2d9f1ab6bba19a9dd"}, + {file = "numpy-1.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6adc33561bd1d46f81131d5352348350fc23df4d742bb246cdfca606ea1208"}, + {file = "numpy-1.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e062aa24638bb5018b7841977c360d2f5917268d125c833a686b7cbabbec496c"}, + {file = "numpy-1.26.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:546b7dd7e22f3c6861463bebb000646fa730e55df5ee4a0224408b5694cc6148"}, + {file = "numpy-1.26.0-cp311-cp311-win32.whl", hash = "sha256:c0b45c8b65b79337dee5134d038346d30e109e9e2e9d43464a2970e5c0e93229"}, + {file = "numpy-1.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:eae430ecf5794cb7ae7fa3808740b015aa80747e5266153128ef055975a72b99"}, + {file = "numpy-1.26.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:166b36197e9debc4e384e9c652ba60c0bacc216d0fc89e78f973a9760b503388"}, + {file = "numpy-1.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f042f66d0b4ae6d48e70e28d487376204d3cbf43b84c03bac57e28dac6151581"}, + {file = "numpy-1.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5e18e5b14a7560d8acf1c596688f4dfd19b4f2945b245a71e5af4ddb7422feb"}, + {file = "numpy-1.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f6bad22a791226d0a5c7c27a80a20e11cfe09ad5ef9084d4d3fc4a299cca505"}, + {file = "numpy-1.26.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4acc65dd65da28060e206c8f27a573455ed724e6179941edb19f97e58161bb69"}, + {file = "numpy-1.26.0-cp312-cp312-win32.whl", hash = "sha256:bb0d9a1aaf5f1cb7967320e80690a1d7ff69f1d47ebc5a9bea013e3a21faec95"}, + {file = "numpy-1.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:ee84ca3c58fe48b8ddafdeb1db87388dce2c3c3f701bf447b05e4cfcc3679112"}, + {file = "numpy-1.26.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a873a8180479bc829313e8d9798d5234dfacfc2e8a7ac188418189bb8eafbd2"}, + {file = "numpy-1.26.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:914b28d3215e0c721dc75db3ad6d62f51f630cb0c277e6b3bcb39519bed10bd8"}, + {file = "numpy-1.26.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c78a22e95182fb2e7874712433eaa610478a3caf86f28c621708d35fa4fd6e7f"}, + {file = "numpy-1.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f737708b366c36b76e953c46ba5827d8c27b7a8c9d0f471810728e5a2fe57c"}, + {file = "numpy-1.26.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b44e6a09afc12952a7d2a58ca0a2429ee0d49a4f89d83a0a11052da696440e49"}, + {file = "numpy-1.26.0-cp39-cp39-win32.whl", hash = "sha256:5671338034b820c8d58c81ad1dafc0ed5a00771a82fccc71d6438df00302094b"}, + {file = "numpy-1.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:020cdbee66ed46b671429c7265cf00d8ac91c046901c55684954c3958525dab2"}, + {file = "numpy-1.26.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0792824ce2f7ea0c82ed2e4fecc29bb86bee0567a080dacaf2e0a01fe7654369"}, + {file = "numpy-1.26.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d484292eaeb3e84a51432a94f53578689ffdea3f90e10c8b203a99be5af57d8"}, + {file = "numpy-1.26.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:186ba67fad3c60dbe8a3abff3b67a91351100f2661c8e2a80364ae6279720299"}, + {file = "numpy-1.26.0.tar.gz", hash = "sha256:f93fc78fe8bf15afe2b8d6b6499f1c73953169fad1e9a8dd086cdff3190e7fdf"}, ] [[package]] @@ -1371,9 +1413,9 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, {version = ">=1.20.3", markers = "python_version < \"3.10\""}, - {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, + {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -1441,18 +1483,18 @@ files = [ [[package]] name = "pathvalidate" -version = "3.1.0" +version = "3.2.0" description = "pathvalidate is a Python library to sanitize/validate a string such as filenames/file-paths/etc." optional = false python-versions = ">=3.7" files = [ - {file = "pathvalidate-3.1.0-py3-none-any.whl", hash = "sha256:912fd1d2e1a2a6a6f98da36a91f21ed86746473810ff625b9c34f3d06c0caa1d"}, - {file = "pathvalidate-3.1.0.tar.gz", hash = "sha256:426970226e24199fd90d93995d223c1e28bda967cdf4370755a14cdf72a2a8ee"}, + {file = "pathvalidate-3.2.0-py3-none-any.whl", hash = "sha256:cc593caa6299b22b37f228148257997e2fa850eea2daf7e4cc9205cef6908dee"}, + {file = "pathvalidate-3.2.0.tar.gz", hash = "sha256:5e8378cf6712bff67fbe7a8307d99fa8c1a0cb28aa477056f8fc374f0dff24ad"}, ] [package.extras] docs = ["Sphinx (>=2.4)", "sphinx-rtd-theme (>=1.2.2)", "urllib3 (<2)"] -test = ["Faker (>=1.0.8)", "allpairspy (>=2)", "click (>=6.2)", "pytest (>=6.0.1)", "pytest-discord (>=0.1.2)", "pytest-md-report (>=0.3)"] +test = ["Faker (>=1.0.8)", "allpairspy (>=2)", "click (>=6.2)", "pytest (>=6.0.1)", "pytest-discord (>=0.1.4)", "pytest-md-report (>=0.4.1)"] [[package]] name = "pkgutil-resolve-name" @@ -1467,13 +1509,13 @@ files = [ [[package]] name = "plac" -version = "1.3.5" +version = "1.4.0" description = "The smartest command line arguments parser in the world" optional = false python-versions = "*" files = [ - {file = "plac-1.3.5-py2.py3-none-any.whl", hash = "sha256:a8933d21a40fe2cec177a2f96217425a4e889d275aa3e25ecf9a9640ab16d416"}, - {file = "plac-1.3.5.tar.gz", hash = "sha256:38bdd864d0450fb748193aa817b9c458a8f5319fbf97b2261151cfc0a5812090"}, + {file = "plac-1.4.0-py2.py3-none-any.whl", hash = "sha256:6a108d343d61d2b8e770eddd6232dde834012bc005734a688547c482ff65b21a"}, + {file = "plac-1.4.0.tar.gz", hash = "sha256:334864447ab7c43d2a0700d9387f30cff4843a67c02e65b29854705922b43357"}, ] [[package]] @@ -1493,28 +1535,47 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-co [[package]] name = "pluggy" -version = "1.2.0" +version = "1.3.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, - {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "plumbum" +version = "1.8.2" +description = "Plumbum: shell combinators library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "plumbum-1.8.2-py3-none-any.whl", hash = "sha256:3ad9e5f56c6ec98f6f7988f7ea8b52159662ea9e915868d369dbccbfca0e367e"}, + {file = "plumbum-1.8.2.tar.gz", hash = "sha256:9e6dc032f4af952665f32f3206567bc23b7858b1413611afe603a3f8ad9bfd75"}, +] + +[package.dependencies] +pywin32 = {version = "*", markers = "platform_system == \"Windows\" and platform_python_implementation != \"PyPy\""} + +[package.extras] +dev = ["paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"] +docs = ["sphinx (>=4.0.0)", "sphinx-rtd-theme (>=1.0.0)"] +ssh = ["paramiko"] + [[package]] name = "poethepoet" -version = "0.22.0" +version = "0.22.1" description = "A task runner that works well with poetry." optional = false python-versions = ">=3.8" files = [ - {file = "poethepoet-0.22.0-py3-none-any.whl", hash = "sha256:f654e52c19b7c689d5293ab6a065787b21f125884c0b367650292df4f3cb508c"}, - {file = "poethepoet-0.22.0.tar.gz", hash = "sha256:659d7678fd8b349bd40941e3de7d6d386171dab3e7c8babcdcd8ead288c9ea47"}, + {file = "poethepoet-0.22.1-py3-none-any.whl", hash = "sha256:1da4cd00d3b2c44b811c91616a744cf71094a26a299ea9956025162d34eef1a5"}, + {file = "poethepoet-0.22.1.tar.gz", hash = "sha256:e758bcac731fa9ac0b812389589541e32b825c4a1894e16fa90aeb1946ba2823"}, ] [package.dependencies] @@ -1526,13 +1587,13 @@ poetry-plugin = ["poetry (>=1.0,<2.0)"] [[package]] name = "pre-commit" -version = "3.3.3" +version = "3.4.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.8" files = [ - {file = "pre_commit-3.3.3-py2.py3-none-any.whl", hash = "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb"}, - {file = "pre_commit-3.3.3.tar.gz", hash = "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023"}, + {file = "pre_commit-3.4.0-py2.py3-none-any.whl", hash = "sha256:96d529a951f8b677f730a7212442027e8ba53f9b04d217c4c67dc56c393ad945"}, + {file = "pre_commit-3.4.0.tar.gz", hash = "sha256:6bbd5129a64cad4c0dfaeeb12cd8f7ea7e15b77028d985341478c8af3c759522"}, ] [package.dependencies] @@ -1542,6 +1603,20 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" +[[package]] +name = "prompt-toolkit" +version = "3.0.36" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.6.2" +files = [ + {file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"}, + {file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"}, +] + +[package.dependencies] +wcwidth = "*" + [[package]] name = "psutil" version = "5.9.5" @@ -1651,55 +1726,140 @@ tutorial = ["ipykernel", "jinja2", "jupyter-client", "markupsafe", "nbconvert"] [[package]] name = "pydantic" -version = "1.10.12" -description = "Data validation and settings management using python type hints" +version = "2.3.0" +description = "Data validation using Python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"}, - {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"}, - {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"}, - {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"}, - {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"}, - {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"}, - {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"}, - {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"}, - {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"}, - {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"}, - {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"}, - {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"}, - {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"}, - {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"}, - {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"}, - {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"}, - {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"}, - {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"}, - {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"}, - {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"}, - {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"}, - {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"}, - {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"}, - {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"}, - {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"}, - {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"}, - {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"}, - {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"}, - {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"}, - {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"}, - {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"}, - {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"}, - {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"}, - {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"}, - {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"}, - {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"}, + {file = "pydantic-2.3.0-py3-none-any.whl", hash = "sha256:45b5e446c6dfaad9444819a293b921a40e1db1aa61ea08aede0522529ce90e81"}, + {file = "pydantic-2.3.0.tar.gz", hash = "sha256:1607cc106602284cd4a00882986570472f193fde9cb1259bceeaedb26aa79a6d"}, ] [package.dependencies] -typing-extensions = ">=4.2.0" +annotated-types = ">=0.4.0" +pydantic-core = "2.6.3" +typing-extensions = ">=4.6.1" [package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.6.3" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1a0ddaa723c48af27d19f27f1c73bdc615c73686d763388c8683fe34ae777bad"}, + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5cfde4fab34dd1e3a3f7f3db38182ab6c95e4ea91cf322242ee0be5c2f7e3d2f"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5493a7027bfc6b108e17c3383959485087d5942e87eb62bbac69829eae9bc1f7"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84e87c16f582f5c753b7f39a71bd6647255512191be2d2dbf49458c4ef024588"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:522a9c4a4d1924facce7270c84b5134c5cabcb01513213662a2e89cf28c1d309"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaafc776e5edc72b3cad1ccedb5fd869cc5c9a591f1213aa9eba31a781be9ac1"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a750a83b2728299ca12e003d73d1264ad0440f60f4fc9cee54acc489249b728"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e8b374ef41ad5c461efb7a140ce4730661aadf85958b5c6a3e9cf4e040ff4bb"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b594b64e8568cf09ee5c9501ede37066b9fc41d83d58f55b9952e32141256acd"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a20c533cb80466c1d42a43a4521669ccad7cf2967830ac62c2c2f9cece63e7e"}, + {file = "pydantic_core-2.6.3-cp310-none-win32.whl", hash = "sha256:04fe5c0a43dec39aedba0ec9579001061d4653a9b53a1366b113aca4a3c05ca7"}, + {file = "pydantic_core-2.6.3-cp310-none-win_amd64.whl", hash = "sha256:6bf7d610ac8f0065a286002a23bcce241ea8248c71988bda538edcc90e0c39ad"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50"}, + {file = "pydantic_core-2.6.3-cp311-none-win32.whl", hash = "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8"}, + {file = "pydantic_core-2.6.3-cp311-none-win_amd64.whl", hash = "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950"}, + {file = "pydantic_core-2.6.3-cp311-none-win_arm64.whl", hash = "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa"}, + {file = "pydantic_core-2.6.3-cp312-none-win32.whl", hash = "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1"}, + {file = "pydantic_core-2.6.3-cp312-none-win_amd64.whl", hash = "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881"}, + {file = "pydantic_core-2.6.3-cp312-none-win_arm64.whl", hash = "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:a53e3195f134bde03620d87a7e2b2f2046e0e5a8195e66d0f244d6d5b2f6d31b"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:f2969e8f72c6236c51f91fbb79c33821d12a811e2a94b7aa59c65f8dbdfad34a"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:672174480a85386dd2e681cadd7d951471ad0bb028ed744c895f11f9d51b9ebe"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:002d0ea50e17ed982c2d65b480bd975fc41086a5a2f9c924ef8fc54419d1dea3"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ccc13afee44b9006a73d2046068d4df96dc5b333bf3509d9a06d1b42db6d8bf"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:439a0de139556745ae53f9cc9668c6c2053444af940d3ef3ecad95b079bc9987"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d63b7545d489422d417a0cae6f9898618669608750fc5e62156957e609e728a5"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b44c42edc07a50a081672e25dfe6022554b47f91e793066a7b601ca290f71e42"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1c721bfc575d57305dd922e6a40a8fe3f762905851d694245807a351ad255c58"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e4a2cf8c4543f37f5dc881de6c190de08096c53986381daebb56a355be5dfe6"}, + {file = "pydantic_core-2.6.3-cp37-none-win32.whl", hash = "sha256:d9b4916b21931b08096efed090327f8fe78e09ae8f5ad44e07f5c72a7eedb51b"}, + {file = "pydantic_core-2.6.3-cp37-none-win_amd64.whl", hash = "sha256:a8acc9dedd304da161eb071cc7ff1326aa5b66aadec9622b2574ad3ffe225525"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5e9c068f36b9f396399d43bfb6defd4cc99c36215f6ff33ac8b9c14ba15bdf6b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e61eae9b31799c32c5f9b7be906be3380e699e74b2db26c227c50a5fc7988698"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85463560c67fc65cd86153a4975d0b720b6d7725cf7ee0b2d291288433fc21b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9616567800bdc83ce136e5847d41008a1d602213d024207b0ff6cab6753fe645"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e9b65a55bbabda7fccd3500192a79f6e474d8d36e78d1685496aad5f9dbd92c"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f468d520f47807d1eb5d27648393519655eadc578d5dd862d06873cce04c4d1b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9680dd23055dd874173a3a63a44e7f5a13885a4cfd7e84814be71be24fba83db"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a718d56c4d55efcfc63f680f207c9f19c8376e5a8a67773535e6f7e80e93170"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8ecbac050856eb6c3046dea655b39216597e373aa8e50e134c0e202f9c47efec"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:788be9844a6e5c4612b74512a76b2153f1877cd845410d756841f6c3420230eb"}, + {file = "pydantic_core-2.6.3-cp38-none-win32.whl", hash = "sha256:07a1aec07333bf5adebd8264047d3dc518563d92aca6f2f5b36f505132399efc"}, + {file = "pydantic_core-2.6.3-cp38-none-win_amd64.whl", hash = "sha256:621afe25cc2b3c4ba05fff53525156d5100eb35c6e5a7cf31d66cc9e1963e378"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:813aab5bfb19c98ae370952b6f7190f1e28e565909bfc219a0909db168783465"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:50555ba3cb58f9861b7a48c493636b996a617db1a72c18da4d7f16d7b1b9952b"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e20f8baedd7d987bd3f8005c146e6bcbda7cdeefc36fad50c66adb2dd2da48"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b0a5d7edb76c1c57b95df719af703e796fc8e796447a1da939f97bfa8a918d60"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f06e21ad0b504658a3a9edd3d8530e8cea5723f6ea5d280e8db8efc625b47e49"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea053cefa008fda40f92aab937fb9f183cf8752e41dbc7bc68917884454c6362"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:171a4718860790f66d6c2eda1d95dd1edf64f864d2e9f9115840840cf5b5713f"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ed7ceca6aba5331ece96c0e328cd52f0dcf942b8895a1ed2642de50800b79d3"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:acafc4368b289a9f291e204d2c4c75908557d4f36bd3ae937914d4529bf62a76"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1aa712ba150d5105814e53cb141412217146fedc22621e9acff9236d77d2a5ef"}, + {file = "pydantic_core-2.6.3-cp39-none-win32.whl", hash = "sha256:44b4f937b992394a2e81a5c5ce716f3dcc1237281e81b80c748b2da6dd5cf29a"}, + {file = "pydantic_core-2.6.3-cp39-none-win_amd64.whl", hash = "sha256:9b33bf9658cb29ac1a517c11e865112316d09687d767d7a0e4a63d5c640d1b17"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149"}, + {file = "pydantic_core-2.6.3.tar.gz", hash = "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pyfakefs" @@ -1771,13 +1931,13 @@ dev = ["twine (>=3.4.1)"] [[package]] name = "pytest" -version = "7.4.0" +version = "7.4.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, - {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, + {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, + {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, ] [package.dependencies] @@ -1876,32 +2036,15 @@ files = [ [package.dependencies] six = ">=1.5" -[[package]] -name = "python-slugify" -version = "8.0.1" -description = "A Python slugify application that also handles Unicode" -optional = false -python-versions = ">=3.7" -files = [ - {file = "python-slugify-8.0.1.tar.gz", hash = "sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27"}, - {file = "python_slugify-8.0.1-py2.py3-none-any.whl", hash = "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395"}, -] - -[package.dependencies] -text-unidecode = ">=1.3" - -[package.extras] -unidecode = ["Unidecode (>=1.1.1)"] - [[package]] name = "pytz" -version = "2023.3" +version = "2023.3.post1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, - {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, ] [[package]] @@ -1976,6 +2119,37 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "pyyaml-include" +version = "1.3.1" +description = "Extending PyYAML with a custom constructor for including YAML files within YAML files" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyyaml-include-1.3.1.tar.gz", hash = "sha256:4cb3b4e1baae2ec251808fe1e8aed5d3d20699c541864c8e47ed866ab2f15039"}, + {file = "pyyaml_include-1.3.1-py3-none-any.whl", hash = "sha256:e58525721a2938d29c4046350f8aad86f848660a770c29605e6f2700925fa753"}, +] + +[package.dependencies] +PyYAML = ">=5.1,<7.0" + +[package.extras] +toml = ["toml"] + +[[package]] +name = "questionary" +version = "2.0.1" +description = "Python library to build pretty command line user prompts โญ๏ธ" +optional = false +python-versions = ">=3.8" +files = [ + {file = "questionary-2.0.1-py3-none-any.whl", hash = "sha256:8ab9a01d0b91b68444dff7f6652c1e754105533f083cbe27597c8110ecc230a2"}, + {file = "questionary-2.0.1.tar.gz", hash = "sha256:bcce898bf3dbb446ff62830c86c5c6fb9a22a54146f0f5597d3da43b10d8fc8b"}, +] + +[package.dependencies] +prompt_toolkit = ">=2.0,<=3.0.36" + [[package]] name = "referencing" version = "0.30.2" @@ -2012,6 +2186,25 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "requests-mock" +version = "1.11.0" +description = "Mock out responses from the requests package" +optional = false +python-versions = "*" +files = [ + {file = "requests-mock-1.11.0.tar.gz", hash = "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4"}, + {file = "requests_mock-1.11.0-py2.py3-none-any.whl", hash = "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15"}, +] + +[package.dependencies] +requests = ">=2.3,<3" +six = "*" + +[package.extras] +fixture = ["fixtures"] +test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] + [[package]] name = "reretry" version = "0.11.8" @@ -2023,129 +2216,110 @@ files = [ {file = "reretry-0.11.8.tar.gz", hash = "sha256:f2791fcebe512ea2f1d153a2874778523a8064860b591cd90afc21a8bed432e3"}, ] -[[package]] -name = "rich" -version = "13.5.2" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "rich-13.5.2-py3-none-any.whl", hash = "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808"}, - {file = "rich-13.5.2.tar.gz", hash = "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - [[package]] name = "rpds-py" -version = "0.9.2" +version = "0.10.3" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.9.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:ab6919a09c055c9b092798ce18c6c4adf49d24d4d9e43a92b257e3f2548231e7"}, - {file = "rpds_py-0.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d55777a80f78dd09410bd84ff8c95ee05519f41113b2df90a69622f5540c4f8b"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a216b26e5af0a8e265d4efd65d3bcec5fba6b26909014effe20cd302fd1138fa"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29cd8bfb2d716366a035913ced99188a79b623a3512292963d84d3e06e63b496"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44659b1f326214950a8204a248ca6199535e73a694be8d3e0e869f820767f12f"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:745f5a43fdd7d6d25a53ab1a99979e7f8ea419dfefebcab0a5a1e9095490ee5e"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a987578ac5214f18b99d1f2a3851cba5b09f4a689818a106c23dbad0dfeb760f"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf4151acb541b6e895354f6ff9ac06995ad9e4175cbc6d30aaed08856558201f"}, - {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:03421628f0dc10a4119d714a17f646e2837126a25ac7a256bdf7c3943400f67f"}, - {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:13b602dc3e8dff3063734f02dcf05111e887f301fdda74151a93dbbc249930fe"}, - {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fae5cb554b604b3f9e2c608241b5d8d303e410d7dfb6d397c335f983495ce7f6"}, - {file = "rpds_py-0.9.2-cp310-none-win32.whl", hash = "sha256:47c5f58a8e0c2c920cc7783113df2fc4ff12bf3a411d985012f145e9242a2764"}, - {file = "rpds_py-0.9.2-cp310-none-win_amd64.whl", hash = "sha256:4ea6b73c22d8182dff91155af018b11aac9ff7eca085750455c5990cb1cfae6e"}, - {file = "rpds_py-0.9.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e564d2238512c5ef5e9d79338ab77f1cbbda6c2d541ad41b2af445fb200385e3"}, - {file = "rpds_py-0.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f411330a6376fb50e5b7a3e66894e4a39e60ca2e17dce258d53768fea06a37bd"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e7521f5af0233e89939ad626b15278c71b69dc1dfccaa7b97bd4cdf96536bb7"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d3335c03100a073883857e91db9f2e0ef8a1cf42dc0369cbb9151c149dbbc1b"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d25b1c1096ef0447355f7293fbe9ad740f7c47ae032c2884113f8e87660d8f6e"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a5d3fbd02efd9cf6a8ffc2f17b53a33542f6b154e88dd7b42ef4a4c0700fdad"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5934e2833afeaf36bd1eadb57256239785f5af0220ed8d21c2896ec4d3a765f"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:095b460e117685867d45548fbd8598a8d9999227e9061ee7f012d9d264e6048d"}, - {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:91378d9f4151adc223d584489591dbb79f78814c0734a7c3bfa9c9e09978121c"}, - {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:24a81c177379300220e907e9b864107614b144f6c2a15ed5c3450e19cf536fae"}, - {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:de0b6eceb46141984671802d412568d22c6bacc9b230174f9e55fc72ef4f57de"}, - {file = "rpds_py-0.9.2-cp311-none-win32.whl", hash = "sha256:700375326ed641f3d9d32060a91513ad668bcb7e2cffb18415c399acb25de2ab"}, - {file = "rpds_py-0.9.2-cp311-none-win_amd64.whl", hash = "sha256:0766babfcf941db8607bdaf82569ec38107dbb03c7f0b72604a0b346b6eb3298"}, - {file = "rpds_py-0.9.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1440c291db3f98a914e1afd9d6541e8fc60b4c3aab1a9008d03da4651e67386"}, - {file = "rpds_py-0.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0f2996fbac8e0b77fd67102becb9229986396e051f33dbceada3debaacc7033f"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f30d205755566a25f2ae0382944fcae2f350500ae4df4e795efa9e850821d82"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:159fba751a1e6b1c69244e23ba6c28f879a8758a3e992ed056d86d74a194a0f3"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1f044792e1adcea82468a72310c66a7f08728d72a244730d14880cd1dabe36b"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9251eb8aa82e6cf88510530b29eef4fac825a2b709baf5b94a6094894f252387"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01899794b654e616c8625b194ddd1e5b51ef5b60ed61baa7a2d9c2ad7b2a4238"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0c43f8ae8f6be1d605b0465671124aa8d6a0e40f1fb81dcea28b7e3d87ca1e1"}, - {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:207f57c402d1f8712618f737356e4b6f35253b6d20a324d9a47cb9f38ee43a6b"}, - {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b52e7c5ae35b00566d244ffefba0f46bb6bec749a50412acf42b1c3f402e2c90"}, - {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:978fa96dbb005d599ec4fd9ed301b1cc45f1a8f7982d4793faf20b404b56677d"}, - {file = "rpds_py-0.9.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6aa8326a4a608e1c28da191edd7c924dff445251b94653988efb059b16577a4d"}, - {file = "rpds_py-0.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aad51239bee6bff6823bbbdc8ad85136c6125542bbc609e035ab98ca1e32a192"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd4dc3602370679c2dfb818d9c97b1137d4dd412230cfecd3c66a1bf388a196"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd9da77c6ec1f258387957b754f0df60766ac23ed698b61941ba9acccd3284d1"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:190ca6f55042ea4649ed19c9093a9be9d63cd8a97880106747d7147f88a49d18"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:876bf9ed62323bc7dcfc261dbc5572c996ef26fe6406b0ff985cbcf460fc8a4c"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa2818759aba55df50592ecbc95ebcdc99917fa7b55cc6796235b04193eb3c55"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9ea4d00850ef1e917815e59b078ecb338f6a8efda23369677c54a5825dbebb55"}, - {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5855c85eb8b8a968a74dc7fb014c9166a05e7e7a8377fb91d78512900aadd13d"}, - {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:14c408e9d1a80dcb45c05a5149e5961aadb912fff42ca1dd9b68c0044904eb32"}, - {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:65a0583c43d9f22cb2130c7b110e695fff834fd5e832a776a107197e59a1898e"}, - {file = "rpds_py-0.9.2-cp38-none-win32.whl", hash = "sha256:71f2f7715935a61fa3e4ae91d91b67e571aeb5cb5d10331ab681256bda2ad920"}, - {file = "rpds_py-0.9.2-cp38-none-win_amd64.whl", hash = "sha256:674c704605092e3ebbbd13687b09c9f78c362a4bc710343efe37a91457123044"}, - {file = "rpds_py-0.9.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:07e2c54bef6838fa44c48dfbc8234e8e2466d851124b551fc4e07a1cfeb37260"}, - {file = "rpds_py-0.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7fdf55283ad38c33e35e2855565361f4bf0abd02470b8ab28d499c663bc5d7c"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:890ba852c16ace6ed9f90e8670f2c1c178d96510a21b06d2fa12d8783a905193"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50025635ba8b629a86d9d5474e650da304cb46bbb4d18690532dd79341467846"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:517cbf6e67ae3623c5127206489d69eb2bdb27239a3c3cc559350ef52a3bbf0b"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0836d71ca19071090d524739420a61580f3f894618d10b666cf3d9a1688355b1"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c439fd54b2b9053717cca3de9583be6584b384d88d045f97d409f0ca867d80f"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f68996a3b3dc9335037f82754f9cdbe3a95db42bde571d8c3be26cc6245f2324"}, - {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7d68dc8acded354c972116f59b5eb2e5864432948e098c19fe6994926d8e15c3"}, - {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f963c6b1218b96db85fc37a9f0851eaf8b9040aa46dec112611697a7023da535"}, - {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a46859d7f947061b4010e554ccd1791467d1b1759f2dc2ec9055fa239f1bc26"}, - {file = "rpds_py-0.9.2-cp39-none-win32.whl", hash = "sha256:e07e5dbf8a83c66783a9fe2d4566968ea8c161199680e8ad38d53e075df5f0d0"}, - {file = "rpds_py-0.9.2-cp39-none-win_amd64.whl", hash = "sha256:682726178138ea45a0766907957b60f3a1bf3acdf212436be9733f28b6c5af3c"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:196cb208825a8b9c8fc360dc0f87993b8b260038615230242bf18ec84447c08d"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c7671d45530fcb6d5e22fd40c97e1e1e01965fc298cbda523bb640f3d923b387"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83b32f0940adec65099f3b1c215ef7f1d025d13ff947975a055989cb7fd019a4"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f67da97f5b9eac838b6980fc6da268622e91f8960e083a34533ca710bec8611"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03975db5f103997904c37e804e5f340c8fdabbb5883f26ee50a255d664eed58c"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:987b06d1cdb28f88a42e4fb8a87f094e43f3c435ed8e486533aea0bf2e53d931"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c861a7e4aef15ff91233751619ce3a3d2b9e5877e0fcd76f9ea4f6847183aa16"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02938432352359805b6da099c9c95c8a0547fe4b274ce8f1a91677401bb9a45f"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ef1f08f2a924837e112cba2953e15aacfccbbfcd773b4b9b4723f8f2ddded08e"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:35da5cc5cb37c04c4ee03128ad59b8c3941a1e5cd398d78c37f716f32a9b7f67"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:141acb9d4ccc04e704e5992d35472f78c35af047fa0cfae2923835d153f091be"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:79f594919d2c1a0cc17d1988a6adaf9a2f000d2e1048f71f298b056b1018e872"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:a06418fe1155e72e16dddc68bb3780ae44cebb2912fbd8bb6ff9161de56e1798"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2eb034c94b0b96d5eddb290b7b5198460e2d5d0c421751713953a9c4e47d10"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b08605d248b974eb02f40bdcd1a35d3924c83a2a5e8f5d0fa5af852c4d960af"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0805911caedfe2736935250be5008b261f10a729a303f676d3d5fea6900c96a"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab2299e3f92aa5417d5e16bb45bb4586171c1327568f638e8453c9f8d9e0f020"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c8d7594e38cf98d8a7df25b440f684b510cf4627fe038c297a87496d10a174f"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b9ec12ad5f0a4625db34db7e0005be2632c1013b253a4a60e8302ad4d462afd"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1fcdee18fea97238ed17ab6478c66b2095e4ae7177e35fb71fbe561a27adf620"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:933a7d5cd4b84f959aedeb84f2030f0a01d63ae6cf256629af3081cf3e3426e8"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:686ba516e02db6d6f8c279d1641f7067ebb5dc58b1d0536c4aaebb7bf01cdc5d"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0173c0444bec0a3d7d848eaeca2d8bd32a1b43f3d3fde6617aac3731fa4be05f"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d576c3ef8c7b2d560e301eb33891d1944d965a4d7a2eacb6332eee8a71827db6"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed89861ee8c8c47d6beb742a602f912b1bb64f598b1e2f3d758948721d44d468"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1054a08e818f8e18910f1bee731583fe8f899b0a0a5044c6e680ceea34f93876"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99e7c4bb27ff1aab90dcc3e9d37ee5af0231ed98d99cb6f5250de28889a3d502"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c545d9d14d47be716495076b659db179206e3fd997769bc01e2d550eeb685596"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9039a11bca3c41be5a58282ed81ae422fa680409022b996032a43badef2a3752"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fb39aca7a64ad0c9490adfa719dbeeb87d13be137ca189d2564e596f8ba32c07"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2d8b3b3a2ce0eaa00c5bbbb60b6713e94e7e0becab7b3db6c5c77f979e8ed1f1"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:99b1c16f732b3a9971406fbfe18468592c5a3529585a45a35adbc1389a529a03"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c27ee01a6c3223025f4badd533bea5e87c988cb0ba2811b690395dfe16088cfe"}, - {file = "rpds_py-0.9.2.tar.gz", hash = "sha256:8d70e8f14900f2657c249ea4def963bed86a29b81f81f5b76b5a9215680de945"}, + {file = "rpds_py-0.10.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:485747ee62da83366a44fbba963c5fe017860ad408ccd6cd99aa66ea80d32b2e"}, + {file = "rpds_py-0.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c55f9821f88e8bee4b7a72c82cfb5ecd22b6aad04033334f33c329b29bfa4da0"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3b52a67ac66a3a64a7e710ba629f62d1e26ca0504c29ee8cbd99b97df7079a8"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3aed39db2f0ace76faa94f465d4234aac72e2f32b009f15da6492a561b3bbebd"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271c360fdc464fe6a75f13ea0c08ddf71a321f4c55fc20a3fe62ea3ef09df7d9"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef5fddfb264e89c435be4adb3953cef5d2936fdeb4463b4161a6ba2f22e7b740"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a771417c9c06c56c9d53d11a5b084d1de75de82978e23c544270ab25e7c066ff"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:52b5cbc0469328e58180021138207e6ec91d7ca2e037d3549cc9e34e2187330a"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6ac3fefb0d168c7c6cab24fdfc80ec62cd2b4dfd9e65b84bdceb1cb01d385c33"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8d54bbdf5d56e2c8cf81a1857250f3ea132de77af543d0ba5dce667183b61fec"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cd2163f42868865597d89399a01aa33b7594ce8e2c4a28503127c81a2f17784e"}, + {file = "rpds_py-0.10.3-cp310-none-win32.whl", hash = "sha256:ea93163472db26ac6043e8f7f93a05d9b59e0505c760da2a3cd22c7dd7111391"}, + {file = "rpds_py-0.10.3-cp310-none-win_amd64.whl", hash = "sha256:7cd020b1fb41e3ab7716d4d2c3972d4588fdfbab9bfbbb64acc7078eccef8860"}, + {file = "rpds_py-0.10.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:1d9b5ee46dcb498fa3e46d4dfabcb531e1f2e76b477e0d99ef114f17bbd38453"}, + {file = "rpds_py-0.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:563646d74a4b4456d0cf3b714ca522e725243c603e8254ad85c3b59b7c0c4bf0"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e626b864725680cd3904414d72e7b0bd81c0e5b2b53a5b30b4273034253bb41f"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485301ee56ce87a51ccb182a4b180d852c5cb2b3cb3a82f7d4714b4141119d8c"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42f712b4668831c0cd85e0a5b5a308700fe068e37dcd24c0062904c4e372b093"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c9141af27a4e5819d74d67d227d5047a20fa3c7d4d9df43037a955b4c748ec5"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef750a20de1b65657a1425f77c525b0183eac63fe7b8f5ac0dd16f3668d3e64f"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e1a0ffc39f51aa5f5c22114a8f1906b3c17eba68c5babb86c5f77d8b1bba14d1"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f4c179a7aeae10ddf44c6bac87938134c1379c49c884529f090f9bf05566c836"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:176287bb998fd1e9846a9b666e240e58f8d3373e3bf87e7642f15af5405187b8"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6446002739ca29249f0beaaf067fcbc2b5aab4bc7ee8fb941bd194947ce19aff"}, + {file = "rpds_py-0.10.3-cp311-none-win32.whl", hash = "sha256:c7aed97f2e676561416c927b063802c8a6285e9b55e1b83213dfd99a8f4f9e48"}, + {file = "rpds_py-0.10.3-cp311-none-win_amd64.whl", hash = "sha256:8bd01ff4032abaed03f2db702fa9a61078bee37add0bd884a6190b05e63b028c"}, + {file = "rpds_py-0.10.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:4cf0855a842c5b5c391dd32ca273b09e86abf8367572073bd1edfc52bc44446b"}, + {file = "rpds_py-0.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:69b857a7d8bd4f5d6e0db4086da8c46309a26e8cefdfc778c0c5cc17d4b11e08"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:975382d9aa90dc59253d6a83a5ca72e07f4ada3ae3d6c0575ced513db322b8ec"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35fbd23c1c8732cde7a94abe7fb071ec173c2f58c0bd0d7e5b669fdfc80a2c7b"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:106af1653007cc569d5fbb5f08c6648a49fe4de74c2df814e234e282ebc06957"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce5e7504db95b76fc89055c7f41e367eaadef5b1d059e27e1d6eabf2b55ca314"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aca759ada6b1967fcfd4336dcf460d02a8a23e6abe06e90ea7881e5c22c4de6"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b5d4bdd697195f3876d134101c40c7d06d46c6ab25159ed5cbd44105c715278a"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a657250807b6efd19b28f5922520ae002a54cb43c2401e6f3d0230c352564d25"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:177c9dd834cdf4dc39c27436ade6fdf9fe81484758885f2d616d5d03c0a83bd2"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e22491d25f97199fc3581ad8dd8ce198d8c8fdb8dae80dea3512e1ce6d5fa99f"}, + {file = "rpds_py-0.10.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:2f3e1867dd574014253b4b8f01ba443b9c914e61d45f3674e452a915d6e929a3"}, + {file = "rpds_py-0.10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c22211c165166de6683de8136229721f3d5c8606cc2c3d1562da9a3a5058049c"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40bc802a696887b14c002edd43c18082cb7b6f9ee8b838239b03b56574d97f71"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e271dd97c7bb8eefda5cca38cd0b0373a1fea50f71e8071376b46968582af9b"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95cde244e7195b2c07ec9b73fa4c5026d4a27233451485caa1cd0c1b55f26dbd"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08a80cf4884920863623a9ee9a285ee04cef57ebedc1cc87b3e3e0f24c8acfe5"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763ad59e105fca09705d9f9b29ecffb95ecdc3b0363be3bb56081b2c6de7977a"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:187700668c018a7e76e89424b7c1042f317c8df9161f00c0c903c82b0a8cac5c"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5267cfda873ad62591b9332fd9472d2409f7cf02a34a9c9cb367e2c0255994bf"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:2ed83d53a8c5902ec48b90b2ac045e28e1698c0bea9441af9409fc844dc79496"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:255f1a10ae39b52122cce26ce0781f7a616f502feecce9e616976f6a87992d6b"}, + {file = "rpds_py-0.10.3-cp38-none-win32.whl", hash = "sha256:a019a344312d0b1f429c00d49c3be62fa273d4a1094e1b224f403716b6d03be1"}, + {file = "rpds_py-0.10.3-cp38-none-win_amd64.whl", hash = "sha256:efb9ece97e696bb56e31166a9dd7919f8f0c6b31967b454718c6509f29ef6fee"}, + {file = "rpds_py-0.10.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:570cc326e78ff23dec7f41487aa9c3dffd02e5ee9ab43a8f6ccc3df8f9327623"}, + {file = "rpds_py-0.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cff7351c251c7546407827b6a37bcef6416304fc54d12d44dbfecbb717064717"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:177914f81f66c86c012311f8c7f46887ec375cfcfd2a2f28233a3053ac93a569"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:448a66b8266de0b581246ca7cd6a73b8d98d15100fb7165974535fa3b577340e"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bbac1953c17252f9cc675bb19372444aadf0179b5df575ac4b56faaec9f6294"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dd9d9d9e898b9d30683bdd2b6c1849449158647d1049a125879cb397ee9cd12"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8c71ea77536149e36c4c784f6d420ffd20bea041e3ba21ed021cb40ce58e2c9"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16a472300bc6c83fe4c2072cc22b3972f90d718d56f241adabc7ae509f53f154"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b9255e7165083de7c1d605e818025e8860636348f34a79d84ec533546064f07e"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:53d7a3cd46cdc1689296348cb05ffd4f4280035770aee0c8ead3bbd4d6529acc"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22da15b902f9f8e267020d1c8bcfc4831ca646fecb60254f7bc71763569f56b1"}, + {file = "rpds_py-0.10.3-cp39-none-win32.whl", hash = "sha256:850c272e0e0d1a5c5d73b1b7871b0a7c2446b304cec55ccdb3eaac0d792bb065"}, + {file = "rpds_py-0.10.3-cp39-none-win_amd64.whl", hash = "sha256:de61e424062173b4f70eec07e12469edde7e17fa180019a2a0d75c13a5c5dc57"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:af247fd4f12cca4129c1b82090244ea5a9d5bb089e9a82feb5a2f7c6a9fe181d"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ad59efe24a4d54c2742929001f2d02803aafc15d6d781c21379e3f7f66ec842"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642ed0a209ced4be3a46f8cb094f2d76f1f479e2a1ceca6de6346a096cd3409d"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37d0c59548ae56fae01c14998918d04ee0d5d3277363c10208eef8c4e2b68ed6"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aad6ed9e70ddfb34d849b761fb243be58c735be6a9265b9060d6ddb77751e3e8"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f94fdd756ba1f79f988855d948ae0bad9ddf44df296770d9a58c774cfbcca72"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77076bdc8776a2b029e1e6ffbe6d7056e35f56f5e80d9dc0bad26ad4a024a762"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87d9b206b1bd7a0523375dc2020a6ce88bca5330682ae2fe25e86fd5d45cea9c"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8efaeb08ede95066da3a3e3c420fcc0a21693fcd0c4396d0585b019613d28515"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a4d9bfda3f84fc563868fe25ca160c8ff0e69bc4443c5647f960d59400ce6557"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d27aa6bbc1f33be920bb7adbb95581452cdf23005d5611b29a12bb6a3468cc95"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ed8313809571a5463fd7db43aaca68ecb43ca7a58f5b23b6e6c6c5d02bdc7882"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:e10e6a1ed2b8661201e79dff5531f8ad4cdd83548a0f81c95cf79b3184b20c33"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:015de2ce2af1586ff5dc873e804434185199a15f7d96920ce67e50604592cae9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae87137951bb3dc08c7d8bfb8988d8c119f3230731b08a71146e84aaa919a7a9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0bb4f48bd0dd18eebe826395e6a48b7331291078a879295bae4e5d053be50d4c"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:09362f86ec201288d5687d1dc476b07bf39c08478cde837cb710b302864e7ec9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821392559d37759caa67d622d0d2994c7a3f2fb29274948ac799d496d92bca73"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7170cbde4070dc3c77dec82abf86f3b210633d4f89550fa0ad2d4b549a05572a"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:5de11c041486681ce854c814844f4ce3282b6ea1656faae19208ebe09d31c5b8"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:4ed172d0c79f156c1b954e99c03bc2e3033c17efce8dd1a7c781bc4d5793dfac"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:11fdd1192240dda8d6c5d18a06146e9045cb7e3ba7c06de6973000ff035df7c6"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f602881d80ee4228a2355c68da6b296a296cd22bbb91e5418d54577bbf17fa7c"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:691d50c99a937709ac4c4cd570d959a006bd6a6d970a484c84cc99543d4a5bbb"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24cd91a03543a0f8d09cb18d1cb27df80a84b5553d2bd94cba5979ef6af5c6e7"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc2200e79d75b5238c8d69f6a30f8284290c777039d331e7340b6c17cad24a5a"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea65b59882d5fa8c74a23f8960db579e5e341534934f43f3b18ec1839b893e41"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:829e91f3a8574888b73e7a3feb3b1af698e717513597e23136ff4eba0bc8387a"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eab75a8569a095f2ad470b342f2751d9902f7944704f0571c8af46bede438475"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:061c3ff1f51ecec256e916cf71cc01f9975af8fb3af9b94d3c0cc8702cfea637"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:39d05e65f23a0fe897b6ac395f2a8d48c56ac0f583f5d663e0afec1da89b95da"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:4eca20917a06d2fca7628ef3c8b94a8c358f6b43f1a621c9815243462dcccf97"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e8d0f0eca087630d58b8c662085529781fd5dc80f0a54eda42d5c9029f812599"}, + {file = "rpds_py-0.10.3.tar.gz", hash = "sha256:fcc1ebb7561a3e24a6588f7c6ded15d80aec22c66a070c757559b57b17ffd1cb"}, ] [[package]] @@ -2256,19 +2430,19 @@ test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeo [[package]] name = "setuptools" -version = "68.1.2" +version = "68.2.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"}, - {file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"}, + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "simplejson" @@ -2377,13 +2551,13 @@ files = [ [[package]] name = "smart-open" -version = "6.3.0" +version = "6.4.0" description = "Utils for streaming large files (S3, HDFS, GCS, Azure Blob Storage, gzip, bz2...)" optional = false python-versions = ">=3.6,<4.0" files = [ - {file = "smart_open-6.3.0-py3-none-any.whl", hash = "sha256:b4c9ae193ad6d3e7add50944b86afa0d150bd821ab8ec21edb26d9a06b66f6a8"}, - {file = "smart_open-6.3.0.tar.gz", hash = "sha256:d5238825fe9a9340645fac3d75b287c08fbb99fb2b422477de781c9f5f09e019"}, + {file = "smart_open-6.4.0-py3-none-any.whl", hash = "sha256:8d3ef7e6997e8e42dd55c74166ed21e6ac70664caa32dd940b26d54a8f6b4142"}, + {file = "smart_open-6.4.0.tar.gz", hash = "sha256:be3c92c246fbe80ebce8fbacb180494a481a77fcdcb7c1aadb2ea5b9c2bee8b9"}, ] [package.extras] @@ -2398,23 +2572,23 @@ webhdfs = ["requests"] [[package]] name = "smmap" -version = "5.0.0" +version = "5.0.1" description = "A pure Python implementation of a sliding window memory map manager" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, + {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, + {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, ] [[package]] name = "snakemake" -version = "7.32.3" +version = "7.32.4" description = "Workflow management system to create reproducible and scalable data analyses" optional = false python-versions = ">=3.7" files = [ - {file = "snakemake-7.32.3.tar.gz", hash = "sha256:cbe586fe28349982307f008ca40e839d569cf5d540008b0c91ebfef689b49b18"}, + {file = "snakemake-7.32.4.tar.gz", hash = "sha256:fdc3f15dd7b06fabb7da30d460e0a3b1fba08e4ea91f9c32c47a83705cdc7b6e"}, ] [package.dependencies] @@ -2462,56 +2636,56 @@ files = [ [[package]] name = "sqlalchemy" -version = "2.0.20" +version = "2.0.21" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.20-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759b51346aa388c2e606ee206c0bc6f15a5299f6174d1e10cadbe4530d3c7a98"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1506e988ebeaaf316f183da601f24eedd7452e163010ea63dbe52dc91c7fc70e"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5768c268df78bacbde166b48be788b83dddaa2a5974b8810af422ddfe68a9bc8"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3f0dd6d15b6dc8b28a838a5c48ced7455c3e1fb47b89da9c79cc2090b072a50"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:243d0fb261f80a26774829bc2cee71df3222587ac789b7eaf6555c5b15651eed"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6eb6d77c31e1bf4268b4d61b549c341cbff9842f8e115ba6904249c20cb78a61"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-win32.whl", hash = "sha256:bcb04441f370cbe6e37c2b8d79e4af9e4789f626c595899d94abebe8b38f9a4d"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-win_amd64.whl", hash = "sha256:d32b5ffef6c5bcb452723a496bad2d4c52b346240c59b3e6dba279f6dcc06c14"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd81466bdbc82b060c3c110b2937ab65ace41dfa7b18681fdfad2f37f27acdd7"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6fe7d61dc71119e21ddb0094ee994418c12f68c61b3d263ebaae50ea8399c4d4"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4e571af672e1bb710b3cc1a9794b55bce1eae5aed41a608c0401885e3491179"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3364b7066b3c7f4437dd345d47271f1251e0cfb0aba67e785343cdbdb0fff08c"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1be86ccea0c965a1e8cd6ccf6884b924c319fcc85765f16c69f1ae7148eba64b"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1d35d49a972649b5080557c603110620a86aa11db350d7a7cb0f0a3f611948a0"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-win32.whl", hash = "sha256:27d554ef5d12501898d88d255c54eef8414576f34672e02fe96d75908993cf53"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-win_amd64.whl", hash = "sha256:411e7f140200c02c4b953b3dbd08351c9f9818d2bd591b56d0fa0716bd014f1e"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3c6aceebbc47db04f2d779db03afeaa2c73ea3f8dcd3987eb9efdb987ffa09a3"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d3f175410a6db0ad96b10bfbb0a5530ecd4fcf1e2b5d83d968dd64791f810ed"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea8186be85da6587456c9ddc7bf480ebad1a0e6dcbad3967c4821233a4d4df57"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c3d99ba99007dab8233f635c32b5cd24fb1df8d64e17bc7df136cedbea427897"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:76fdfc0f6f5341987474ff48e7a66c3cd2b8a71ddda01fa82fedb180b961630a"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-win32.whl", hash = "sha256:d3793dcf5bc4d74ae1e9db15121250c2da476e1af8e45a1d9a52b1513a393459"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-win_amd64.whl", hash = "sha256:79fde625a0a55220d3624e64101ed68a059c1c1f126c74f08a42097a72ff66a9"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:599ccd23a7146e126be1c7632d1d47847fa9f333104d03325c4e15440fc7d927"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1a58052b5a93425f656675673ef1f7e005a3b72e3f2c91b8acca1b27ccadf5f4"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79543f945be7a5ada9943d555cf9b1531cfea49241809dd1183701f94a748624"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63e73da7fb030ae0a46a9ffbeef7e892f5def4baf8064786d040d45c1d6d1dc5"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ce5e81b800a8afc870bb8e0a275d81957e16f8c4b62415a7b386f29a0cb9763"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb0d3e94c2a84215532d9bcf10229476ffd3b08f481c53754113b794afb62d14"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-win32.whl", hash = "sha256:8dd77fd6648b677d7742d2c3cc105a66e2681cc5e5fb247b88c7a7b78351cf74"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-win_amd64.whl", hash = "sha256:6f8a934f9dfdf762c844e5164046a9cea25fabbc9ec865c023fe7f300f11ca4a"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:26a3399eaf65e9ab2690c07bd5cf898b639e76903e0abad096cd609233ce5208"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4cde2e1096cbb3e62002efdb7050113aa5f01718035ba9f29f9d89c3758e7e4e"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b09ba72e4e6d341bb5bdd3564f1cea6095d4c3632e45dc69375a1dbe4e26ec"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b74eeafaa11372627ce94e4dc88a6751b2b4d263015b3523e2b1e57291102f0"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:77d37c1b4e64c926fa3de23e8244b964aab92963d0f74d98cbc0783a9e04f501"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:eefebcc5c555803065128401a1e224a64607259b5eb907021bf9b175f315d2a6"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-win32.whl", hash = "sha256:3423dc2a3b94125094897118b52bdf4d37daf142cbcf26d48af284b763ab90e9"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-win_amd64.whl", hash = "sha256:5ed61e3463021763b853628aef8bc5d469fe12d95f82c74ef605049d810f3267"}, - {file = "SQLAlchemy-2.0.20-py3-none-any.whl", hash = "sha256:63a368231c53c93e2b67d0c5556a9836fdcd383f7e3026a39602aad775b14acf"}, - {file = "SQLAlchemy-2.0.20.tar.gz", hash = "sha256:ca8a5ff2aa7f3ade6c498aaafce25b1eaeabe4e42b73e25519183e4566a16fc6"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e7dc99b23e33c71d720c4ae37ebb095bebebbd31a24b7d99dfc4753d2803ede"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7f0c4ee579acfe6c994637527c386d1c22eb60bc1c1d36d940d8477e482095d4"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f7d57a7e140efe69ce2d7b057c3f9a595f98d0bbdfc23fd055efdfbaa46e3a5"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca38746eac23dd7c20bec9278d2058c7ad662b2f1576e4c3dbfcd7c00cc48fa"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3cf229704074bce31f7f47d12883afee3b0a02bb233a0ba45ddbfe542939cca4"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb87f763b5d04a82ae84ccff25554ffd903baafba6698e18ebaf32561f2fe4aa"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-win32.whl", hash = "sha256:89e274604abb1a7fd5c14867a412c9d49c08ccf6ce3e1e04fffc068b5b6499d4"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-win_amd64.whl", hash = "sha256:e36339a68126ffb708dc6d1948161cea2a9e85d7d7b0c54f6999853d70d44430"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf8eebccc66829010f06fbd2b80095d7872991bfe8415098b9fe47deaaa58063"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b977bfce15afa53d9cf6a632482d7968477625f030d86a109f7bdfe8ce3c064a"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff3dc2f60dbf82c9e599c2915db1526d65415be323464f84de8db3e361ba5b9"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44ac5c89b6896f4740e7091f4a0ff2e62881da80c239dd9408f84f75a293dae9"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:87bf91ebf15258c4701d71dcdd9c4ba39521fb6a37379ea68088ce8cd869b446"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-win32.whl", hash = "sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-win_amd64.whl", hash = "sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8c323813963b2503e54d0944813cd479c10c636e3ee223bcbd7bd478bf53c178"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:419b1276b55925b5ac9b4c7044e999f1787c69761a3c9756dec6e5c225ceca01"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-win32.whl", hash = "sha256:4615623a490e46be85fbaa6335f35cf80e61df0783240afe7d4f544778c315a9"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-win_amd64.whl", hash = "sha256:cca720d05389ab1a5877ff05af96551e58ba65e8dc65582d849ac83ddde3e231"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b4eae01faee9f2b17f08885e3f047153ae0416648f8e8c8bd9bc677c5ce64be9"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3eb7c03fe1cd3255811cd4e74db1ab8dca22074d50cd8937edf4ef62d758cdf4"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2d494b6a2a2d05fb99f01b84cc9af9f5f93bf3e1e5dbdafe4bed0c2823584c1"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b19ae41ef26c01a987e49e37c77b9ad060c59f94d3b3efdfdbf4f3daaca7b5fe"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fc6b15465fabccc94bf7e38777d665b6a4f95efd1725049d6184b3a39fd54880"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:014794b60d2021cc8ae0f91d4d0331fe92691ae5467a00841f7130fe877b678e"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-win32.whl", hash = "sha256:0268256a34806e5d1c8f7ee93277d7ea8cc8ae391f487213139018b6805aeaf6"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-win_amd64.whl", hash = "sha256:73c079e21d10ff2be54a4699f55865d4b275fd6c8bd5d90c5b1ef78ae0197301"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:785e2f2c1cb50d0a44e2cdeea5fd36b5bf2d79c481c10f3a88a8be4cfa2c4615"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c111cd40910ffcb615b33605fc8f8e22146aeb7933d06569ac90f219818345ef"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cba4e7369de663611ce7460a34be48e999e0bbb1feb9130070f0685e9a6b66"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a69067af86ec7f11a8e50ba85544657b1477aabf64fa447fd3736b5a0a4f67"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ccb99c3138c9bde118b51a289d90096a3791658da9aea1754667302ed6564f6e"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:513fd5b6513d37e985eb5b7ed89da5fd9e72354e3523980ef00d439bc549c9e9"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-win32.whl", hash = "sha256:f9fefd6298433b6e9188252f3bff53b9ff0443c8fde27298b8a2b19f6617eeb9"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-win_amd64.whl", hash = "sha256:2e617727fe4091cedb3e4409b39368f424934c7faa78171749f704b49b4bb4ce"}, + {file = "SQLAlchemy-2.0.21-py3-none-any.whl", hash = "sha256:ea7da25ee458d8f404b93eb073116156fd7d8c2a776d8311534851f28277b4ce"}, + {file = "SQLAlchemy-2.0.21.tar.gz", hash = "sha256:05b971ab1ac2994a14c56b35eaaa91f86ba080e9ad481b20d99d77f381bb6258"}, ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} typing-extensions = ">=4.2.0" [package.extras] @@ -2590,17 +2764,6 @@ files = [ [package.extras] tests = ["pytest", "pytest-cov"] -[[package]] -name = "text-unidecode" -version = "1.3" -description = "The most basic Text::Unidecode port" -optional = false -python-versions = "*" -files = [ - {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, - {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, -] - [[package]] name = "throttler" version = "1.2.2" @@ -2639,28 +2802,28 @@ files = [ [[package]] name = "traitlets" -version = "5.9.0" +version = "5.10.0" description = "Traitlets Python configuration system" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, - {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, + {file = "traitlets-5.10.0-py3-none-any.whl", hash = "sha256:417745a96681fbb358e723d5346a547521f36e9bd0d50ba7ab368fff5d67aa54"}, + {file = "traitlets-5.10.0.tar.gz", hash = "sha256:f584ea209240466e66e91f3c81aa7d004ba4cf794990b0c775938a1544217cd1"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.5.1)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] [[package]] name = "typing-extensions" -version = "4.7.1" -description = "Backported and Experimental Type Hints for Python 3.7+" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, - {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, ] [[package]] @@ -2676,39 +2839,38 @@ files = [ [[package]] name = "ubelt" -version = "1.3.3" +version = "1.3.2" description = "A Python utility belt containing simple tools, a stdlib like feel, and extra batteries." optional = false python-versions = ">=3.6" files = [ - {file = "ubelt-1.3.3-py3-none-any.whl", hash = "sha256:7e5a0975609312db93a76ae2a1e81ded50f2aca1be28c9b1783e7fd9b49f5f47"}, - {file = "ubelt-1.3.3.tar.gz", hash = "sha256:482c5c34844a887c02ffed69b2305bd09872755223d638383b2df8bc69f4dbdd"}, + {file = "ubelt-1.3.2-py3-none-any.whl", hash = "sha256:abd5a4998ce84abab30b55c2e99a3e805f00bd8db14bdeb470838a134a340a6d"}, + {file = "ubelt-1.3.2.tar.gz", hash = "sha256:15e09c5628aefb82d2022e4fb12b35cf30fd27112f8c492212208972a24acc19"}, ] [package.dependencies] "jaraco.windows" = {version = "*", markers = "platform_system == \"Windows\""} -pydantic = {version = "<2.0", markers = "platform_system == \"Windows\" and platform_python_implementation == \"PyPy\""} [package.extras] -all = ["Pygments", "colorama", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "jaraco.windows", "numpy", "numpy", "numpy", "numpy", "numpy", "numpy", "pydantic (<2.0)", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-timeout", "python-dateutil", "requests", "xdoctest", "xxhash", "xxhash", "xxhash", "xxhash", "xxhash", "xxhash"] -all-strict = ["Pygments (==2.2.0)", "colorama (==0.4.3)", "coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "jaraco.windows (==3.9.1)", "numpy (==1.12.0)", "numpy (==1.14.5)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.1)", "numpy (==1.23.5)", "pydantic (<2.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "python-dateutil (==2.8.1)", "requests (==2.25.1)", "xdoctest (==0.14.0)", "xxhash (==1.3.0)", "xxhash (==1.3.0)", "xxhash (==1.4.3)", "xxhash (==2.0.2)", "xxhash (==3.0.0)", "xxhash (==3.2.0)"] +all = ["Pygments", "colorama", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "jaraco.windows", "numpy", "numpy", "numpy", "numpy", "numpy", "numpy", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-timeout", "python-dateutil", "requests", "xdoctest", "xxhash", "xxhash", "xxhash", "xxhash", "xxhash", "xxhash"] +all-strict = ["Pygments (==2.2.0)", "colorama (==0.4.3)", "coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "jaraco.windows (==3.9.1)", "numpy (==1.12.0)", "numpy (==1.14.5)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.1)", "numpy (==1.23.5)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "python-dateutil (==2.8.1)", "requests (==2.25.1)", "xdoctest (==0.14.0)", "xxhash (==1.3.0)", "xxhash (==1.3.0)", "xxhash (==1.4.3)", "xxhash (==2.0.2)", "xxhash (==3.0.0)", "xxhash (==3.2.0)"] docs = ["Pygments", "myst-parser", "sphinx", "sphinx-autoapi", "sphinx-autobuild", "sphinx-reredirects", "sphinx-rtd-theme", "sphinxcontrib-napoleon"] docs-strict = ["Pygments (==2.9.0)", "myst-parser (==0.16.1)", "sphinx (==4.3.2)", "sphinx-autoapi (==1.8.4)", "sphinx-autobuild (==2021.3.14)", "sphinx-reredirects (==0.0.1)", "sphinx-rtd-theme (==1.0.0)", "sphinxcontrib-napoleon (==0.7)"] optional = ["Pygments", "colorama", "numpy", "numpy", "numpy", "numpy", "numpy", "numpy", "python-dateutil", "xxhash", "xxhash", "xxhash", "xxhash", "xxhash", "xxhash"] optional-strict = ["Pygments (==2.2.0)", "colorama (==0.4.3)", "numpy (==1.12.0)", "numpy (==1.14.5)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.1)", "numpy (==1.23.5)", "python-dateutil (==2.8.1)", "xxhash (==1.3.0)", "xxhash (==1.3.0)", "xxhash (==1.4.3)", "xxhash (==2.0.2)", "xxhash (==3.0.0)", "xxhash (==3.2.0)"] -runtime-strict = ["jaraco.windows (==3.9.1)", "pydantic (<2.0)"] +runtime-strict = ["jaraco.windows (==3.9.1)"] tests = ["coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "coverage", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-timeout", "requests", "xdoctest"] tests-strict = ["coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "requests (==2.25.1)", "xdoctest (==0.14.0)"] [[package]] name = "urllib3" -version = "2.0.4" +version = "2.0.5" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.7" files = [ - {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"}, - {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"}, + {file = "urllib3-2.0.5-py3-none-any.whl", hash = "sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e"}, + {file = "urllib3-2.0.5.tar.gz", hash = "sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594"}, ] [package.extras] @@ -2719,13 +2881,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.24.3" +version = "20.24.5" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.24.3-py3-none-any.whl", hash = "sha256:95a6e9398b4967fbcb5fef2acec5efaf9aa4972049d9ae41f95e0972a683fd02"}, - {file = "virtualenv-20.24.3.tar.gz", hash = "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc"}, + {file = "virtualenv-20.24.5-py3-none-any.whl", hash = "sha256:b80039f280f4919c77b30f1c23294ae357c4c8701042086e3fc005963e4e537b"}, + {file = "virtualenv-20.24.5.tar.gz", hash = "sha256:e8361967f6da6fbdf1426483bfe9fca8287c242ac0bc30429905721cefbff752"}, ] [package.dependencies] @@ -2734,9 +2896,20 @@ filelock = ">=3.12.2,<4" platformdirs = ">=3.9.1,<4" [package.extras] -docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +[[package]] +name = "wcwidth" +version = "0.2.6" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, + {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, +] + [[package]] name = "wrapt" version = "1.15.0" @@ -2839,20 +3012,20 @@ pyyaml = ">=6.0,<7.0" [[package]] name = "zipp" -version = "3.16.2" +version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, - {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.12" -content-hash = "48195b8d03dd2392cc9356c9784345bcd1e65105b6e8bc4c21a14db5045deab1" +content-hash = "ee44d16e76daecd66db38c73509de996fbfb41ebe50cf1066daee05cd936b854" diff --git a/pyproject.toml b/pyproject.toml index 8bf4bd04..39cda011 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,9 +12,7 @@ authors = [ "Jason Kai ", ] license = "MIT" -packages = [ - { include = "snakebids" } -] +packages = [{ include = "snakebids" }] exclude = ["snakebids/tests/**"] [tool.poetry-dynamic-versioning] @@ -26,12 +24,11 @@ bump = true [tool.poetry-dynamic-versioning.substitution] files = [ - 'snakebids/project_template/cookiecutter.json', - 'snakebids/__init__.py' + 'snakebids/__init__.py', ] patterns = [ "(^\\s+\"snakebids_version\":\\s*\")[^'\"]*(\")", - "(^__version__\\s*(?::.*?)?=\\s*['\"])[^'\"]*(['\"])" + "(^__version__\\s*(?::.*?)?=\\s*['\"])[^'\"]*(['\"])", ] [tool.poetry.dependencies] @@ -42,7 +39,6 @@ snakemake = [ { version = ">=7.18.2", python = ">=3.11" }, ] PyYAML = "^6" -cookiecutter = "^2.1.1" typing-extensions = ">=3.10.0" attrs = ">=21.2.0,<24" boutiques = "^0.5.25" @@ -57,13 +53,18 @@ importlib-resources = ">=5.12.0,<7" # on the python version being used. numpy = [ { version = "<=1.24.4", python = "<3.9" }, - { version = ">=1.23.2", python = ">=3.11" } + { version = ">=1.23.2", python = ">=3.11" }, ] # Use minimum of 1.10.0 because of security vulnerability scipy = [ { version = ">=1.10.0,<=1.10.1", python = "<3.9" }, - { version = ">=1.10.0", python = ">=3.9" } + { version = ">=1.10.0", python = ">=3.9" }, ] +# minimum 8.2.0 to use post-copy mesages +copier = ">=8.2.0" +jinja2-time = ">=0.2.0" +# minimum 2.31.0 because of security vulnerability +requests = ">=2.31.0" [tool.poetry.group.dev.dependencies] black = "^23.1.0" @@ -80,10 +81,13 @@ pyparsing = "^3.0.9" # Version 1.1.312-1.1.315 have a false positive handling some nested function # calls pathvalidate = "^3.0.0" -pyright = ">=1.1.324" +# As of pyright==1.1.327 only 1.1.324 is bug free +pyright = "==1.1.324" ruff = "^0.0.285" pytest-xdist = "^3.3.1" pytest-split = "^0.8.1" +tomli = "^2.0.1" +requests-mock = "^1.11.0" [tool.poetry.scripts] snakebids = "snakebids.admin:main" @@ -94,8 +98,8 @@ build-backend = "poetry_dynamic_versioning.backend" [tool.poe.tasks] setup = "pre-commit install" -quality = { shell = "isort snakebids && black snakebids && ruff snakebids && pyright" } -fix = { shell = "ruff --fix snakebids && isort snakebids && black snakebids"} +quality.shell = "isort snakebids && black snakebids && ruff snakebids && pyright snakebids" +fix.shell = "ruff --fix snakebids && isort snakebids && black snakebids" test = """ pytest --doctest-modules --ignore=docs \ --ignore=snakebids/project_template --benchmark-disable @@ -103,6 +107,24 @@ pytest --doctest-modules --ignore=docs \ mkinit = "mkinit --recursive --nomods --black -i snakebids" benchmark = "pytest --benchmark-only --benchmark-autosave" +[tool.poe.tasks._get_version] +imports = ["platform"] +expr = "platform.python_version()" + +[tool.poe.tasks.build-container] +args = [{ name = "container_id", positional = true, required = true }] +uses = { VERSION = "_get_version" } +cmd = """ + docker build 'containers/${container_id}' \ + --tag 'snakebids/${container_id}:${VERSION}' \ + --build-arg="PYTHON_VERSION=${VERSION}" +""" + +[tool.pytest.ini_options] +markers = [ + "docker: marks tests as requiring docker (deselect with '-m \"not docker\"')", +] + [tool.isort] profile = "black" multi_line_output = 3 @@ -116,11 +138,11 @@ reportImportCycles = false [tool.ruff] select = [ - "E", # pycodestyle error - "F", # pyflakes - "PL", # pylint - "RUF", # ruff - "UP", #pyupgrade + "E", # pycodestyle error + "F", # pyflakes + "PL", # pylint + "RUF", # ruff + "UP", #pyupgrade "T100", # debugger ] ignore = ["PLR0913"] diff --git a/snakebids/admin.py b/snakebids/admin.py index 4b75f21f..c75110a5 100644 --- a/snakebids/admin.py +++ b/snakebids/admin.py @@ -1,10 +1,13 @@ """Script to generate a Snakebids project.""" import argparse +import re +import sys from pathlib import Path +import copier import more_itertools as itx -from cookiecutter.main import cookiecutter # type: ignore +from colorama import Fore, Style import snakebids from snakebids.app import SnakeBidsApp @@ -12,14 +15,38 @@ def create_app(args: argparse.Namespace) -> None: - cookiecutter( - str(Path(itx.first(snakebids.__path__)) / "project_template"), - output_dir=args.output_dir, + output = Path(args.output_dir).resolve() + if not output.parent.exists(): + print( + f"{Fore.RED}{Style.BRIGHT}{output.parent}{Style.RESET_ALL}{Fore.RED} does " + f"not exist{Fore.RESET}", + file=sys.stderr, + ) + sys.exit(1) + if not re.match(r"^[a-zA-Z_][a-zA-Z_0-9]*$", output.name): + print( + f"{Fore.RED}Output directory name {Style.BRIGHT}{output.name}" + f"{Style.RESET_ALL}{Fore.RED} is not a valid python module name", + file=sys.stderr, + ) + sys.exit(1) + print( + f"Creating Snakebids app at {Fore.GREEN}{output}{Fore.RESET}", file=sys.stderr ) + print(file=sys.stderr) + try: + copier.run_copy( + str(Path(itx.first(snakebids.__path__), "project_template")), + output, + data={"app_full_name": output.name}, + unsafe=True, + ) + except KeyboardInterrupt: + print(f"{Fore.RED}Aborted!{Fore.RESET}", file=sys.stderr) + sys.exit(1) def create_descriptor(args: argparse.Namespace) -> None: - # pylint: disable=unsubscriptable-object app = SnakeBidsApp(args.app_dir.resolve()) add_dynamic_args(app.parser, app.config["parse_args"], app.config["pybids_inputs"]) app.create_descriptor(args.out_path) @@ -57,7 +84,7 @@ def gen_parser() -> argparse.ArgumentParser: def main() -> None: - """Invoke Cookiecutter on the Snakebids project template.""" + """Invoke Snakebids cli.""" parser = gen_parser() args = parser.parse_args() diff --git a/snakebids/core/datasets.py b/snakebids/core/datasets.py index 1c910ed2..928aef62 100644 --- a/snakebids/core/datasets.py +++ b/snakebids/core/datasets.py @@ -69,7 +69,7 @@ def __repr__(self) -> str: return f'{self.__class__.__name__}({list(self._data)}, entity="{self.entity}")' @property - def entities(self) -> tuple[str]: + def entities(self) -> tuple[str, ...]: """The unique values associated with the component""" return tuple(set(self._data)) diff --git a/snakebids/io/printing.py b/snakebids/io/printing.py index 90dd2990..b7f719ad 100644 --- a/snakebids/io/printing.py +++ b/snakebids/io/printing.py @@ -12,7 +12,12 @@ def quote_wrap(val: str) -> str: - return json.dumps(val, ensure_ascii=False) + return ( + json.dumps(val, ensure_ascii=False) + .replace("\x85", "\\x85") + .replace("\u2028", "\\u2028") + .replace("\u2029", "\\u2029") + ) def format_zip_lists( diff --git a/snakebids/jinja2_ext/__init__.py b/snakebids/jinja2_ext/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/snakebids/jinja2_ext/colorama.py b/snakebids/jinja2_ext/colorama.py new file mode 100644 index 00000000..927b40bf --- /dev/null +++ b/snakebids/jinja2_ext/colorama.py @@ -0,0 +1,11 @@ +from __future__ import annotations + +import jinja2.parser +from colorama import Fore +from jinja2.ext import Extension + + +class ColoramaExtension(Extension): + def __init__(self, env: jinja2.Environment): + super().__init__(env) + env.globals["Fore"] = Fore # type: ignore diff --git a/snakebids/jinja2_ext/snakebids_version.py b/snakebids/jinja2_ext/snakebids_version.py new file mode 100644 index 00000000..04c9eb7d --- /dev/null +++ b/snakebids/jinja2_ext/snakebids_version.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +import importlib.metadata as impm +import re + +import jinja2.parser +import requests +from jinja2.ext import Extension + + +class SnakebidsVersionExtension(Extension): + def __init__(self, env: jinja2.Environment): + env.globals["snakebids_version"] = self._lookup_version() # type: ignore + super().__init__(env) + + def _lookup_version(self): + request = requests.get("https://pypi.org/pypi/snakebids/json") + version_regex = re.compile(r"\d+\.\d+\.\d+") + try: + request.raise_for_status() + version = request.json()["info"]["version"] + if not re.fullmatch(version_regex, version): + raise TypeError() + return version + except (requests.HTTPError, KeyError, TypeError): + version = impm.version("snakebids") + if version == "0.0.0" or not re.fullmatch(version_regex, version): + return None + return version diff --git a/snakebids/jinja2_ext/toml_encode.py b/snakebids/jinja2_ext/toml_encode.py new file mode 100644 index 00000000..c76e475c --- /dev/null +++ b/snakebids/jinja2_ext/toml_encode.py @@ -0,0 +1,13 @@ +import json + +import jinja2 +from jinja2.ext import Extension + + +def toml_string(item: str): + return json.dumps(item, ensure_ascii=False).replace("\x7F", "\\u007f") + + +class TomlEncodeExtension(Extension): + def __init__(self, env: jinja2.Environment): + env.filters["toml_string"] = toml_string # type: ignore diff --git a/snakebids/jinja2_ext/vcs.py b/snakebids/jinja2_ext/vcs.py new file mode 100644 index 00000000..b7478ca6 --- /dev/null +++ b/snakebids/jinja2_ext/vcs.py @@ -0,0 +1,79 @@ +from __future__ import annotations + +import re +import subprocess +import sys +from pathlib import Path + +import jinja2.parser +from jinja2 import nodes +from jinja2.ext import Extension + + +class GitConfigExtension(Extension): + tags = {"gitconfig"} # noqa: RUF012 + _config: dict[str, str] + + def __init__(self, env: jinja2.Environment) -> None: + self._config = {} + + try: + config_list = subprocess.check_output( + [executable(), "config", "-l"], stderr=subprocess.STDOUT + ).decode() + + m = re.findall("(?ms)^([^=]+)=(.*?)$", config_list) + if m: + for group in m: + self._config[group[0]] = group[1] + except (subprocess.CalledProcessError, OSError): + pass + + def get(self, key: str, default: str | None = None) -> str | None: + return self._config.get(key, default) + + def __getitem__(self, item: str) -> str: + return self._config[item] + + def parse(self, parser: jinja2.parser.Parser): + lineno = next(parser.stream).lineno + + node = parser.parse_expression() + + if not isinstance(node, nodes.Const): + raise ValueError("Argument to `gitconfig` must be a string") + call_method = self.call_method( + "get", + [node], + lineno=lineno, + ) + return nodes.Output([call_method], lineno=lineno) + + +def executable() -> str: + _executable = None + + if sys.platform == "win32": + # Finding git via where.exe + where = "%WINDIR%\\System32\\where.exe" + paths = subprocess.check_output( + [where, "git"], shell=True, encoding="oem" + ).split("\n") + for path in paths: + if not path: + continue + + _path = Path(path.strip()) + try: + _path.relative_to(Path.cwd()) + except ValueError: + _executable = str(_path) + + break + else: + _executable = "git" + + if _executable is None: # type: ignore + raise RuntimeError("Unable to find a valid git executable") + + return _executable diff --git a/snakebids/plugins/validator.py b/snakebids/plugins/validator.py index b21fb2d5..7dbe311e 100644 --- a/snakebids/plugins/validator.py +++ b/snakebids/plugins/validator.py @@ -56,7 +56,7 @@ def __call__(self, app: SnakeBidsApp) -> None: temp.flush() try: subprocess.check_call( - ["bids-validator", app.config["bids_dirs"], "-c", temp.name] + ["bids-validator", app.config["bids_dir"], "-c", temp.name] ) # If successfully bids-validation performed diff --git a/snakebids/project_template/README.md.jinja b/snakebids/project_template/README.md.jinja new file mode 100644 index 00000000..c4327223 --- /dev/null +++ b/snakebids/project_template/README.md.jinja @@ -0,0 +1,3 @@ +# {{app_full_name}} + +{{ app_description }} diff --git a/snakebids/project_template/cookiecutter.json b/snakebids/project_template/cookiecutter.json deleted file mode 100644 index f6bcb48d..00000000 --- a/snakebids/project_template/cookiecutter.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "full_name": "", - "email": "", - "github": "", - "app_full_name": "Snakebids App", - "app_description": "", - "create_doc_template": ["False", "True"], - "_app_version": "0.1.0", - "_bids_version": "1.8.0", - "_snakebids_version": "0.0.0", - "__app_name": "{{ cookiecutter.app_full_name|lower|replace(' ', '_')|replace('-', '_') }}" -} diff --git a/snakebids/project_template/copier.yaml b/snakebids/project_template/copier.yaml new file mode 100644 index 00000000..3bb226ef --- /dev/null +++ b/snakebids/project_template/copier.yaml @@ -0,0 +1,144 @@ +app_full_name: + type: str + help: What is the name of your app? + validator: >- + {% if not (app_full_name | regex_search("^[a-zA-Z_][a-zA-Z_0-9]*$")) -%} + Name must be a valid python module name + {%- elif not app_full_name -%} + Required + {%- endif %} + +full_name: + type: str + help: What is your name? + default: '{% gitconfig "user.name" %}' + +email_regex: + default: ^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$ + when: false + +email: + type: str + help: What is your email? + default: '{% gitconfig "user.email" %}' + validator: >- + {% if email and not (email | regex_search(email_regex, ignorecase=True)) %} + Must be a valid email + {% endif %} + +github: + type: str + help: What is your github username? + +app_description: + type: str + help: Provide a brief description of your app + +app_version: + default: "0.1.0" + help: Starting version number for your app + validator: '{% if not app_version %}Required{% endif %}' + +build_system: + help: > + What build system would you like to use? If unsure, choose setuptools + choices: + - setuptools + - poetry + - hatch + - flit + +# Flit and setuptools requires specifying license via Trove classifiers; too +# complicated to get via interactive prompt +license: + default: >- + {% if build_system != "flit" and build_system != "setuptools" %}MIT{% endif %} + help: Usage license for your app + when: "{{ build_system != 'flit' and build_system != 'setuptools' }}" + +create_doc_template: + type: bool + help: Would you to set up basic documentation? + +bids_version: + default: "1.8.0" + when: false + +python_version: + default: ">=3.8,<3.12" + when: false + +snakebids_version: + default: "{{ snakebids_version or '0.9.3' }}" + when: false + +snakemake_version: + default: "7.20" + when: false + +name_slug: + default: "{{ app_full_name|lower|replace(' ', '_')|replace('-', '_') }}" + when: false + +test_run_cmd: + default: "{{ name_slug }} tests/data tests/result participant -c1" + when: false + +_message_after_copy: > + Snakebids project successfully created in + {{ Fore.GREEN }}{{ _copier_conf.dst_path }}{{ Fore.RESET }} + + + Just a few steps before coding: + + + {{ Fore.BLUE }}1.{{ Fore.RESET }} Change into the project directory: + + $ cd {{ _copier_conf.dst_path }} + + {% if build_system == "poetry" -%} + {{ Fore.BLUE }}2.{{ Fore.RESET }} Install dependencies. + + $ poetry install + + {%- else -%} + {{ Fore.BLUE + "2." + Fore.RESET + """ Install dependencies. This may vary + depending on your tooling. The following are examples (the first example + should work on any python environment; the others require 3rd party tools): + """ | wordwrap(80)}} + + * {{Fore.YELLOW}}Virtual Environment and setuptools:{{Fore.RESET}} + $ python -m venv .venv + $ source .venv/bin/activate + $ pip install . + + * {{Fore.YELLOW}}Hatch:{{Fore.RESET}} + $ hatch env create + + * {{Fore.YELLOW}}PDM:{{Fore.RESET}} + $ pdm install + {%- endif %} + + + {{ Fore.BLUE }}3.{{Fore.RESET }} Perform a test run. + + {% if build_system == "poetry" %} + $ poetry run {{ test_run_cmd }} + + {%- else %} + * {{Fore.YELLOW}}Virtual Environment and setuptools:{{Fore.RESET}} + $ {{ test_run_cmd }} + + * {{Fore.YELLOW}}Hatch:{{Fore.RESET}} + $ hatch env run -- {{ test_run_cmd }} + + * {{Fore.YELLOW}}PDM:{{Fore.RESET}} + $ pdm run {{ test_run_cmd }} + {%- endif %} + +_jinja_extensions: + - jinja2_time.TimeExtension + - snakebids.jinja2_ext.vcs.GitConfigExtension + - snakebids.jinja2_ext.colorama.ColoramaExtension + - snakebids.jinja2_ext.toml_encode.TomlEncodeExtension + - snakebids.jinja2_ext.snakebids_version.SnakebidsVersionExtension diff --git a/snakebids/project_template/hooks/post_gen_project.py b/snakebids/project_template/hooks/post_gen_project.py deleted file mode 100644 index 155c3896..00000000 --- a/snakebids/project_template/hooks/post_gen_project.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import annotations - -from importlib import metadata -from shutil import rmtree - - -def update_files(files: list[str] | str, replacement_str: str, cc_variable: str): - """Helper function to update cookiecutter content for certain files - - INPUT - ------ - files - file(s) to be updated - replacement_str - text to substitute into file(s) - cc_var - cookiecutter variable to replace (e.g. - {{ cookiecutter._snakebids_version }}) - """ - for fpath in files: - with open(fpath) as fcontent: - content = fcontent.read() - - content = content.replace(cc_variable, replacement_str) - - with open(fpath, "w", encoding="utf-8") as fcontent: - fcontent.write(content) - - -# Replace snakebids version in cookiecutter -sb_file_lists = ["setup.py", "docs/requirements.txt"] -sb_version = metadata.version("snakebids") -update_files(sb_file_lists, sb_version, "{{ cookiecutter._snakebids_version }}") - -# Remove documentation template -if not {{cookiecutter.create_doc_template}}: # noqa: F821 - rmtree("docs") diff --git a/snakebids/project_template/tests/data/dataset_description.json b/snakebids/project_template/tests/data/dataset_description.json new file mode 100644 index 00000000..cec4e821 --- /dev/null +++ b/snakebids/project_template/tests/data/dataset_description.json @@ -0,0 +1,18 @@ +{ + "Acknowledgements": "Snakebids Development Team", + "Authors": [ + "Peter Van Dyken", + "Ali Khan", + "Tristan Kuehn", + "Jason Kai" + ], + "DatasetType": "raw", + "BIDSVersion": "1.4.1", + "HowToAcknowledge": "https://zenodo.org/record/8274278", + "License": "PDLL", + "Name": "Snakebids Test T1w Dataset (empty files)", + "ReferencesAndLinks": [ + "https://github.com/akhanf/snakebids", + "List of papers or websites" + ] + } diff --git a/snakebids/project_template/tests/data/sub-001 b/snakebids/project_template/tests/data/sub-001 new file mode 120000 index 00000000..30ebd731 --- /dev/null +++ b/snakebids/project_template/tests/data/sub-001 @@ -0,0 +1 @@ +../../../../docs/tutorial/bids/sub-001 \ No newline at end of file diff --git a/snakebids/project_template/{% if build_system != 'poetry' %}pyproject.toml{% endif %}.jinja b/snakebids/project_template/{% if build_system != 'poetry' %}pyproject.toml{% endif %}.jinja new file mode 100644 index 00000000..4633172f --- /dev/null +++ b/snakebids/project_template/{% if build_system != 'poetry' %}pyproject.toml{% endif %}.jinja @@ -0,0 +1,52 @@ +[project] +name = {{ app_full_name | toml_string }} +version = {{ app_version | toml_string }} +description = {{ app_description | toml_string }} +readme = "README.md" +{% if license -%} +license = {{ license | toml_string }} +{%- endif %} +{% if full_name or email -%} +authors = [ + { {{ '' }} + {%- if full_name -%} + name = {{ full_name | toml_string }} + {%- endif -%} + {%- if full_name and email -%} + ,{{ ' ' }} + {%- endif -%} + {%- if email -%} + email = {{ email | toml_string }} + {%- endif -%} + {{ ' ' }}} +] +{%- endif %} +classifiers = [ + "Programming Language :: Python :: 3", + "Operating System :: OS Independent", +] + +requires-python = "{{ python_version }}" +dependencies = [ + "snakemake >= {{ snakemake_version }}", + "snakebids >= {{ snakebids_version }}", + {# Explicitly specify numpy version for py38 until snakebids 0.10.x to + work around specification bug causing numpys too high for py38 to be + locked by pdm -#} + "numpy <=1.24.4; python_version < \"3.9\"", +] + +[project.scripts] +{{ name_slug }} = "{{ name_slug }}.run:main" + +[build-system] +{% if build_system == "flit" -%} +requires = ["flit_core >=3.2,<4"] +build-backend = "flit_core.buildapi" +{%- elif build_system == "hatch" -%} +requires = ["hatchling"] +build-backend = "hatchling.build" +{%- else -%} +requires = ["setuptools"] +build-backend = "setuptools.build_meta" +{%- endif %} diff --git a/snakebids/project_template/{% if build_system == 'poetry' %}pyproject.toml{% endif %}.jinja b/snakebids/project_template/{% if build_system == 'poetry' %}pyproject.toml{% endif %}.jinja new file mode 100644 index 00000000..566c916a --- /dev/null +++ b/snakebids/project_template/{% if build_system == 'poetry' %}pyproject.toml{% endif %}.jinja @@ -0,0 +1,34 @@ +[tool.poetry] +name = "{{ app_full_name }}" +version = {{ app_version | toml_string }} +description = {{ app_description | toml_string }} +readme = "README.md" +{% if license -%} +license = {{ license | toml_string }} +{%- endif %} +{% if full_name -%} +authors = [ + {% if email -%} + {{ (full_name + " <" + email + ">") | toml_string }} + {%- else -%} + {{ full_name | toml_string }} + {%- endif %} +] +{%- endif %} +classifiers = [ + "Programming Language :: Python :: 3", + "Operating System :: OS Independent", +] + +[tool.poetry.dependencies] +python = "{{ python_version }}" +snakemake = ">={{ snakemake_version }}" +snakebids = ">={{ snakebids_version }}" + +[tool.poetry.scripts] +{{ name_slug }} = "{{ name_slug }}.run:main" + + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/snakebids/project_template/{% if build_system == 'setuptools' %}MANIFEST.in{% endif %}.jinja b/snakebids/project_template/{% if build_system == 'setuptools' %}MANIFEST.in{% endif %}.jinja new file mode 100644 index 00000000..cba9b38a --- /dev/null +++ b/snakebids/project_template/{% if build_system == 'setuptools' %}MANIFEST.in{% endif %}.jinja @@ -0,0 +1,5 @@ +include {{ name_slug }}/**/*.yaml +include {{ name_slug }}/**/*.yml +include {{ name_slug }}/**/*.json +include {{ name_slug }}/**/Snakefile +include {{ name_slug }}/**/*.smk diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/.gitignore b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/.gitignore similarity index 100% rename from snakebids/project_template/{{cookiecutter.__app_name}}/docs/.gitignore rename to snakebids/project_template/{% if create_doc_template %}docs{% endif %}/.gitignore diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/Makefile b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/Makefile similarity index 100% rename from snakebids/project_template/{{cookiecutter.__app_name}}/docs/Makefile rename to snakebids/project_template/{% if create_doc_template %}docs{% endif %}/Makefile diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/conf.py b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/conf.py.jinja similarity index 92% rename from snakebids/project_template/{{cookiecutter.__app_name}}/docs/conf.py rename to snakebids/project_template/{% if create_doc_template %}docs{% endif %}/conf.py.jinja index 869f0a12..ad690830 100644 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/conf.py +++ b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/conf.py.jinja @@ -17,9 +17,9 @@ # -- Project information ----------------------------------------------------- -project = "{{cookiecutter.__app_name}}" -copyright = "{% now 'utc', '%Y' %}, {{cookiecutter.full_name}}" -author = "{{cookiecutter.full_name}}" +project = "{{name_slug}}" +copyright = "{% now 'utc', '%Y' %}, {{full_name}}" +author = "{{full_name}}" # -- General configuration --------------------------------------------------- diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/getting_started/installation.md b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/getting_started/installation.md.jinja similarity index 71% rename from snakebids/project_template/{{cookiecutter.__app_name}}/docs/getting_started/installation.md rename to snakebids/project_template/{% if create_doc_template %}docs{% endif %}/getting_started/installation.md.jinja index 56b38bfd..710cc7fe 100644 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/getting_started/installation.md +++ b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/getting_started/installation.md.jinja @@ -3,7 +3,7 @@ Install from github with pip: ```bash -pip install -e git+https://github.com/{{cookiecutter.github}}/{{cookiecutter.__app_name}}#egg={{cookiecutter.__app_name}} +pip install -e git+https://github.com/{{github}}/{{name_slug}}#egg={{name_slug}} ``` Note: you can re-run this command to re-install with the latest version @@ -13,13 +13,13 @@ Note: you can re-run this command to re-install with the latest version Do a dry-run first (`-n`) and simply print (`-p`) what would be run: ```bash -{{cookiecutter.__app_name}} /path/to/bids/dir /path/to/output/dir participant -np +{{name_slug}} /path/to/bids/dir /path/to/output/dir participant -np ``` Run the app, using all cores:: ```bash -{{cookiecutter.__app_name}} /path/to/bids/dir /path/to/output/dir participant --cores all +{{name_slug}} /path/to/bids/dir /path/to/output/dir participant --cores all ``` If any workflow rules require containers, then run with the `--use-singularity` option. @@ -35,22 +35,22 @@ summarize outputs, by using the `report(...)` function on any snakemake output. To generate a report, run: ```bash -{{cookiecutter.__app_name}} /path/to/bids/dir /path/to/output/dir participant --report +{{name_slug}} /path/to/bids/dir /path/to/output/dir participant --report ``` ## Compute Canada Instructions ### Setting up a dev environment -Here are some instructions to get your python environment set-up on graham to run {{ cookiecutter.__app_name }}: +Here are some instructions to get your python environment set-up on graham to run {{name_slug}}: # Create a virtualenv and activate it: ```bash cd $SCRATCH module load python/3 -virtualenv venv_{{ cookiecutter.__app_name }} -source venv_{{ cookiecutter.__app_name }}/bin/activate +virtualenv venv_{{name_slug}} +source venv_{{name_slug}}/bin/activate ``` # Follow the steps above to install from github repository @@ -69,23 +69,23 @@ These are used in the instructions below. In an interactive job (for testing): ```bash -regularInteractive -n 8 {{ cookiecutter.__app_name }} bids_dir out_dir participant --participant_label 001 -j 8 +regularInteractive -n 8 {{name_slug}} bids_dir out_dir participant --participant_label 001 -j 8 ``` Submitting a job (for larger cores, more subjects), still single job, but snakemake will parallelize over the 32 cores: ```bash -regularSubmit -j Fat {{ cookiecutter.__app_name }} bids_dir out_dir participant -j 32 +regularSubmit -j Fat {{name_slug}} bids_dir out_dir participant -j 32 ``` Scaling up to ~hundred subjects (needs cc-slurm snakemake profile installed), submits 1 16core job per subject: ```bash -{{ cookiecutter.__app_name }} bids_dir out_dir participant --profile cc-slurm +{{name_slug}} bids_dir out_dir participant --profile cc-slurm ``` Scaling up to even more subjects (uses group-components to bundle multiple subjects in each job), 1 32core job for N subjects (e.g. 10): ```bash -{{ cookiecutter.__app_name }} bids_dir out_dir participant --profile cc-slurm --group-components subj=10 -``` \ No newline at end of file +{{name_slug}} bids_dir out_dir participant --profile cc-slurm --group-components subj=10 +``` diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/index.md b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/index.md similarity index 100% rename from snakebids/project_template/{{cookiecutter.__app_name}}/docs/index.md rename to snakebids/project_template/{% if create_doc_template %}docs{% endif %}/index.md diff --git a/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/requirements.txt.jinja b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/requirements.txt.jinja new file mode 100644 index 00000000..4af5df61 --- /dev/null +++ b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/requirements.txt.jinja @@ -0,0 +1,4 @@ +docutils<0.18 +sphinx-argparse +sphinx_rtd_theme +snakebids=={{ snakebids_version }} diff --git a/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/usage/app_cli.md.jinja b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/usage/app_cli.md.jinja new file mode 100644 index 00000000..4d3625c1 --- /dev/null +++ b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/usage/app_cli.md.jinja @@ -0,0 +1,7 @@ +## Command line interface + +```{argparse} +:filename: ../{{ name_slug }}/run.py +:func: get_parser +:prog: {{ name_slug }} +``` diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/usage/snakemake_cli.md b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/usage/snakemake_cli.md similarity index 96% rename from snakebids/project_template/{{cookiecutter.__app_name}}/docs/usage/snakemake_cli.md rename to snakebids/project_template/{% if create_doc_template %}docs{% endif %}/usage/snakemake_cli.md index d9b0f6b1..2e834372 100644 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/usage/snakemake_cli.md +++ b/snakebids/project_template/{% if create_doc_template %}docs{% endif %}/usage/snakemake_cli.md @@ -4,4 +4,4 @@ :module: snakemake :func: get_argument_parser :prog: snakemake -``` \ No newline at end of file +``` diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/README.md b/snakebids/project_template/{{cookiecutter.__app_name}}/README.md deleted file mode 100644 index 84b5ca31..00000000 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# {{ cookiecutter.__app_name }} - -{{ cookiecutter.app_description }} diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/requirements.txt b/snakebids/project_template/{{cookiecutter.__app_name}}/docs/requirements.txt deleted file mode 100644 index 21901c99..00000000 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -docutils<0.18 -sphinx-argparse -sphinx_rtd_theme -snakebids=={{ cookiecutter._snakebids_version }} diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/usage/app_cli.md b/snakebids/project_template/{{cookiecutter.__app_name}}/docs/usage/app_cli.md deleted file mode 100644 index e5d49dfb..00000000 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/docs/usage/app_cli.md +++ /dev/null @@ -1,7 +0,0 @@ -## Command line interface - -```{argparse} -:filename: ../{{ cookiecutter.__app_name }}/run.py -:func: get_parser -:prog: {{ cookiecutter.__app_name }} -``` \ No newline at end of file diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/setup.py b/snakebids/project_template/{{cookiecutter.__app_name}}/setup.py deleted file mode 100644 index d4a2e1ef..00000000 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/setup.py +++ /dev/null @@ -1,46 +0,0 @@ -import json - -import setuptools - -with open("README.md", encoding="utf-8") as fh: - long_description = fh.read() - -with open("pipeline_description.json", encoding="utf-8") as fh: - pipeline = json.load(fh) -name = pipeline["GeneratedBy"][0]["Name"] -description = pipeline["Name"] -version = pipeline["GeneratedBy"][0]["Version"] -optional_vals = { - attr: pipeline["GeneratedBy"][0].get(key) - for attr, key in [ - ("url", "CodeURL"), - ("author", "Author"), - ("author_email", "AuthorEmail"), - ] - if key in pipeline -} - -setuptools.setup( - name=name, - version=version, - description=description, - long_description=long_description, - long_description_content_type="text/x-rst", - packages=setuptools.find_packages(), - include_package_data=True, - classifiers=[ - "Programming Language :: Python :: 3", - "Operating System :: OS Independent", - ], - entry_points={ - "console_scripts": [ - "{{cookiecutter.__app_name}}={{cookiecutter.__app_name}}.run:main" - ] - }, - install_requires=[ - "snakebids>={{cookiecutter._snakebids_version}}", - "snakemake", - ], - python_requires=">=3.7", - **optional_vals, -) diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/pipeline_description.json b/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/pipeline_description.json deleted file mode 100644 index e148f804..00000000 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/pipeline_description.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "Name": "Dataset generated by {{ cookiecutter.__app_name }}", - "BIDSVersion": "{{ cookiecutter._bids_version }}", - "DatasetType": "derivative", - "GeneratedBy": [ - { - "Name": "{{ cookiecutter.__app_name }}", - "Version": "{{ cookiecutter._app_version }}"{%- if cookiecutter.github or cookiecutter.full_name or cookiecutter.email -%},{%- endif -%} - {% if cookiecutter.github %} - "CodeURL": "http://github.com/{{ cookiecutter.github }}/{{ cookiecutter.__app_name }}"{%- if cookiecutter.full_name or cookiecutter.email -%},{%- endif -%} - {%- endif -%} - {% if cookiecutter.full_name %} - "Author": "{{ cookiecutter.full_name }}"{%- if cookiecutter.email -%},{%- endif -%} - {%- endif -%} - {% if cookiecutter.email %} - "AuthorEmail": "{{ cookiecutter.email }}"{% endif %} - } - ] -} diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/workflow/Snakefile b/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/workflow/Snakefile deleted file mode 100644 index b934da01..00000000 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/workflow/Snakefile +++ /dev/null @@ -1,53 +0,0 @@ -#---- begin snakebids boilerplate ---------------------------------------------- - -from snakebids import bids, generate_inputs, get_wildcard_constraints - -configfile: workflow.source_path('../config/snakebids.yml') - -# Get input wildcards -inputs = generate_inputs( - bids_dir=config["bids_dir"], - pybids_inputs=config["pybids_inputs"], - pybidsdb_dir=config.get("pybidsdb_dir"), - pybidsdb_reset=config.get("pybidsdb_reset"), - derivatives=config.get("derivatives", None), - participant_label=config.get("participant_label", None), - exclude_participant_label=config.get("exclude_participant_label", None), - validate=not config.get("plugins.validator.skip", False) -) - -#this adds constraints to the bids naming -wildcard_constraints: **get_wildcard_constraints(config['pybids_inputs']) - -#---- end snakebids boilerplate ------------------------------------------------ - - -rule smooth: - input: inputs['bold'].path - output: - bids( - root=config['root'], - datatype='func', - desc='smooth{fwhm}mm', - suffix='bold.nii.gz', - **inputs['bold'].wildcards - ) - container: config['singularity']['fsl'] - log: - bids( - root='logs', - suffix='smooth.log', - fwhm='{fwhm}', - **inputs['bold'].wildcards - ) - params: sigma = lambda wildcards: f'{float(wildcards.fwhm)/2.355:0.2f}' - shell: 'fslmaths {input} -s {params.sigma} {output}' - - -rule all: - input: - inputs['bold'].expand( - rules.smooth.output, - fwhm = config['smoothing_fwhm'], - ) - default_target: True diff --git a/snakebids/project_template/{{name_slug}}/__init__.py b/snakebids/project_template/{{name_slug}}/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/config/snakebids.yml b/snakebids/project_template/{{name_slug}}/config/snakebids.yml similarity index 91% rename from snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/config/snakebids.yml rename to snakebids/project_template/{{name_slug}}/config/snakebids.yml index dd35a12d..f2249d8f 100644 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/config/snakebids.yml +++ b/snakebids/project_template/{{name_slug}}/config/snakebids.yml @@ -22,16 +22,16 @@ targets_by_analysis_level: # https://bids-standard.github.io/pybids/generated/bids.layout.BIDSLayout.html#bids.layout.BIDSLayout.get pybids_inputs: + t1w: + filters: + suffix: T1w + wildcards: + - subject bold: filters: - suffix: 'bold' - extension: '.nii.gz' - datatype: 'func' + suffix: bold wildcards: - subject - - session - - acquisition - - task - run #configuration for the command-line parameters to make available @@ -54,7 +54,7 @@ parse_args: help: Level of the analysis that will be performed. choices: *analysis_levels - --participant_label: + --participant-label: help: The label(s) of the participant(s) that should be analyzed. The label corresponds to sub- from the BIDS spec (so it does not include "sub-"). If this parameter is not @@ -62,7 +62,7 @@ parse_args: participants can be specified with a space separated list. nargs: '+' - --exclude_participant_label: + --exclude-participant-label: help: The label(s) of the participant(s) that should be excluded. The label corresponds to sub- from the BIDS spec (so it does not include "sub-"). If this parameter is not @@ -78,17 +78,14 @@ parse_args: # custom command-line parameters can then be added, these will get added to the config and also accessible to plugins # below are examples for plugin and custom parameters (e.g. config['smoothing_fwhm']) - --skip_bids_validation: + --skip-bids-validation: help: 'Skip validation of BIDS dataset. BIDS validation is performed by - default using the bids-validator plugin (if installed/enabled) or with the pybids + default using the bids-validator plugin (if installed/enabled) or with the pybids validator implementation (if bids-validator is not installed/enabled).' dest: "plugins.validator.skip" action: "store_true" default: False - --smoothing_fwhm: - nargs: '+' - required: True #--- workflow specific configuration -- below is just an example: diff --git a/snakebids/project_template/{{name_slug}}/pipeline_description.json.jinja b/snakebids/project_template/{{name_slug}}/pipeline_description.json.jinja new file mode 100644 index 00000000..ec2c2953 --- /dev/null +++ b/snakebids/project_template/{{name_slug}}/pipeline_description.json.jinja @@ -0,0 +1,22 @@ +{% + set generated = { + "Name": name_slug, + "Version": app_version, + } +-%} +{%- if github -%} + {%- set _ = generated.update({"CodeURL": "https://github.com/" + github + "/" + name_slug}) -%} +{%- endif -%} +{%- if full_name -%} + {%- set _ = generated.update({"Author": full_name}) -%} +{%- endif -%} +{%- if email -%} + {%- set _ = generated.update({"AuthorEmail": email}) -%} +{%- endif -%} +{{- { + "Name": "Dataset generated by " + name_slug, + "BIDSVersion": bids_version, + "DatasetType": "derivative", + "GeneratedBy": [generated], + } | to_json(indent=2) +}} diff --git a/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/run.py b/snakebids/project_template/{{name_slug}}/run.py.jinja similarity index 75% rename from snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/run.py rename to snakebids/project_template/{{name_slug}}/run.py.jinja index 80d4e2c8..1b782c1f 100755 --- a/snakebids/project_template/{{cookiecutter.__app_name}}/{{cookiecutter.__app_name}}/run.py +++ b/snakebids/project_template/{{name_slug}}/run.py.jinja @@ -7,13 +7,13 @@ def get_parser(): """Exposes parser for sphinx doc generation, cwd is the docs dir""" - app = SnakeBidsApp("../{{ cookiecutter.__app_name }}") + app = SnakeBidsApp("../{{ name_slug }}") return app.parser def main(): app = SnakeBidsApp( - Path(__file__).resolve().parent.parent, # to get repository root + Path(__file__).resolve().parent, # to get repository root plugins=[BidsValidator()], ) app.run_snakemake() diff --git a/snakebids/project_template/{{name_slug}}/workflow/Snakefile b/snakebids/project_template/{{name_slug}}/workflow/Snakefile new file mode 100644 index 00000000..079a2d39 --- /dev/null +++ b/snakebids/project_template/{{name_slug}}/workflow/Snakefile @@ -0,0 +1,39 @@ +from snakebids import bids, generate_inputs, get_wildcard_constraints + +configfile: 'config/snakebids.yml' + +# Get input wildcards +inputs = generate_inputs( + bids_dir=config["bids_dir"], + pybids_inputs=config["pybids_inputs"], + pybidsdb_dir=config.get("pybidsdb_dir"), + pybidsdb_reset=config.get("pybidsdb_reset"), + derivatives=config.get("derivatives", None), + participant_label=config.get("participant_label", None), + exclude_participant_label=config.get("exclude_participant_label", None), + validate=not config.get("plugins.validator.skip", False) +) + + +rule all: + input: + inputs['t1w'].expand(), + inputs['bold'].expand() + default_target: True + params: + inputs=lambda wcards, input: "- " + "\n- ".join(input) + shell: + """ + cat < bool: return True -_P = ParamSpec("_P") -_FuncT: TypeAlias = Callable[_P, _T] - - def debug(**overrides: Any): """Disable a hypothesis decorated test with specific parameter examples @@ -137,7 +136,7 @@ def debug(**overrides: Any): when hypothesis is not being used) """ - def inner(func: _FuncT[_P, _T]) -> _FuncT[_P, _T]: + def inner(func: Callable[_P, _T]) -> Callable[_P, _T]: if not hasattr(func, "hypothesis"): raise TypeError(f"{func} is not decorated with hypothesis.given") @@ -261,7 +260,41 @@ def expand_zip_list( it.product(zip_cols, it.product(*new_values.values())), ) ) - return dict(zip(it.chain(zip_list.keys(), new_values.keys()), zip(*new_cols))) + z = zip(*new_cols) + return dict(zip(it.chain(zip_list.keys(), new_values.keys()), z)) + + +def needs_docker(container: str): + def decorator(func: Callable[_P, _T]) -> Callable[_P, _T]: + @pytest.mark.docker + @ft.wraps(func) + def wrapper(*args: _P.args, **kwargs: _P.kwargs): + try: + sp.run(["docker"], check=True) + except (sp.CalledProcessError, FileNotFoundError): + pytest.fail( + "docker is not available on this machine. To skip docker tests, " + "use '-m \"not docker\"'" + ) + try: + sp.run(["docker", "image", "inspect", container], check=True) + except sp.CalledProcessError: + if not (match := re.match(r"snakebids/([\w\-])\:", container)): + pytest.fail( + f"Unrecognized docker image: {container}. Should be " + "'snakebids/{container_id}:{version}" + ) + container_id = match[1] + pytest.fail( + f"{container} is not built on this machine. To build container, " + f"run `poetry run poe build-container {container_id}`. To skip " + "docker tests, use '-m \"not docker\"'" + ) + return func(*args, **kwargs) + + return wrapper + + return decorator def entity_to_wildcard(entities: str | Iterable[str], /): @@ -274,7 +307,7 @@ def identity(obj: _T) -> _T: def example_if(condition: bool, *args: Any, **kwargs: Any): - def inner(func: _FuncT[_P, _T]) -> _FuncT[_P, _T]: + def inner(func: Callable[_P, _T]) -> Callable[_P, _T]: return example(*args, **kwargs)(func) if condition: diff --git a/snakebids/tests/test_admin.py b/snakebids/tests/test_admin.py index 44e0a407..441a6808 100644 --- a/snakebids/tests/test_admin.py +++ b/snakebids/tests/test_admin.py @@ -1,10 +1,16 @@ +import re import sys from argparse import ArgumentParser, Namespace +from pathlib import Path import pytest +from hypothesis import given +from hypothesis import strategies as st +from pathvalidate import Platform, is_valid_filename from pytest_mock.plugin import MockerFixture from snakebids.admin import gen_parser +from snakebids.tests.helpers import allow_function_scoped @pytest.fixture @@ -27,6 +33,52 @@ def test_fails_if_invalid_subcommand( with pytest.raises(SystemExit): parser.parse_args() + @given( + name=st.text() + .filter(lambda s: not re.match(r"^[a-zA-Z_][a-zA-Z_0-9]*$", s)) + .filter(lambda s: is_valid_filename(s, Platform.LINUX)) + .filter(lambda s: s not in {".", ".."}) + ) + @allow_function_scoped + def test_create_fails_with_invalid_filename( + self, + parser: ArgumentParser, + mocker: MockerFixture, + name: str, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], + ): + mocker.patch.object(sys, "argv", ["snakebids", "create", str(tmp_path / name)]) + args = parser.parse_args() + with pytest.raises(SystemExit): + args.func(args) + capture = capsys.readouterr() + assert "valid python module" in capture.err + assert name in capture.err + + @given( + name=st.text() + .filter(lambda s: is_valid_filename(s, Platform.LINUX)) + .filter(lambda s: s not in {".", ".."}) + ) + @allow_function_scoped + def test_create_fails_missing_parent_dir( + self, + parser: ArgumentParser, + mocker: MockerFixture, + name: str, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], + ): + path = tmp_path / name / "sub" + mocker.patch.object(sys, "argv", ["snakebids", "create", str(path)]) + args = parser.parse_args() + with pytest.raises(SystemExit): + args.func(args) + capture = capsys.readouterr() + assert "does not exist" in capture.err + assert str(path.parent) in capture.err + def test_create_succeeds(self, parser: ArgumentParser, mocker: MockerFixture): mocker.patch.object(sys, "argv", ["snakebids", "create"]) assert isinstance(parser.parse_args(), Namespace) diff --git a/snakebids/tests/test_generate_inputs.py b/snakebids/tests/test_generate_inputs.py index 4f01ad5a..71163a94 100644 --- a/snakebids/tests/test_generate_inputs.py +++ b/snakebids/tests/test_generate_inputs.py @@ -556,7 +556,7 @@ def get_subset(of: Iterable[T]) -> list[T]: class TestCustomPaths: @pytest.fixture() - def temp_dir(self, fakefs_tmpdir: Path): + def temp_dir(self, fakefs_tmpdir: Path, bids_fs: Path): return fakefs_tmpdir def generate_test_directory( diff --git a/snakebids/tests/test_template.py b/snakebids/tests/test_template.py index 1f709796..d7fcc4f4 100644 --- a/snakebids/tests/test_template.py +++ b/snakebids/tests/test_template.py @@ -1,42 +1,305 @@ -from os.path import join +from __future__ import annotations + +import platform +import re +import subprocess as sp +import sys +import tempfile from pathlib import Path +from typing import Any, Final, Literal, TypedDict +import copier import more_itertools as itx +import pathvalidate +import prompt_toolkit.validation import pytest -from cookiecutter.main import cookiecutter # type: ignore +import requests_mock +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st +from pytest_mock.plugin import MockerFixture +from typing_extensions import Unpack + +if sys.version_info < (3, 11): + import tomli as tomllib +else: + import tomllib import snakebids -from snakebids.app import SnakeBidsApp -from snakebids.cli import SnakebidsArgs +from snakebids.tests.helpers import allow_function_scoped, needs_docker + +BuildBackend = Literal["poetry", "hatch", "flit", "setuptools"] +BUILD_BACKENDS: Final[list[BuildBackend]] = ["poetry", "hatch", "flit", "setuptools"] + + +class DataFields(TypedDict): + full_name: str + email: str + app_full_name: str + github: str + app_description: str + build_system: BuildBackend + app_version: str + create_doc_template: bool + license: str + + +def get_empty_data(app_name: str, build: BuildBackend) -> DataFields: + data: DataFields = { + "full_name": "", + "email": "", + "app_full_name": app_name, + "github": "", + "app_description": "", + "build_system": build, + "app_version": "0.1.0", + "create_doc_template": False, + "license": "", + } + # poetry we need an author + if build == "poetry": + data["full_name"] = "John Doe" + data["email"] = "example@email.com" + return data + + +# emails complements of https://gist.github.com/cjaoude/fd9910626629b53c4d25 +def invalid_emails(): + return st.sampled_from( + [ + "plainaddress", + "#@%^%#$@#$@#.com", + "@example.com", + "Joe Smith ", + "email.example.com", + "email@example@example.com", + ".email@example.com", + "email.@example.com", + "email..email@example.com", + "ใ‚ใ„ใ†ใˆใŠ@example.com", + "email@example.com (Joe Smith)", + "email@example", + "email@-example.com", + "email@example.web-", + "email@[111.123.123.4444]", + "email@example..com", + "Abc..123@example.com", + r"โ€(),:;<>[\]@example.com", + "justโ€notโ€right@example.com", + r'this\ is"really"not\allowed@example.com', + ] + ) + + +@given(email=invalid_emails()) +@allow_function_scoped +def test_invalid_email_raises_error(email: str, tmp_path: Path): + data = get_empty_data("testapp", "setuptools") + data["email"] = email + with pytest.raises(prompt_toolkit.validation.ValidationError): + copier.run_copy( + str(Path(itx.first(snakebids.__path__), "project_template")), + tmp_path / data["app_full_name"], + data=data, + unsafe=True, + ) -def test_template_dry_runs_successfully(tmp_path: Path): +@pytest.mark.parametrize("build", BUILD_BACKENDS) +@pytest.mark.parametrize( + ["server", "server_status", "metadata", "expected"], + [ + # Server returns valid version + ("1.1.1", 200, "2.2.2", "1.1.1"), + # Server raises 400 error + ("1.1.1", 400, "2.2.2", "2.2.2"), + # server returns invalid and importlib.metadata gives valid + ("1.1.1.dev1", 200, "2.2.2", "2.2.2"), + # server invalid and importlib.metadata gives 0.0.0 + ("1.1.1.dev1", 200, "0.0.0", "0.9.3"), + # server and importlib.metadata invalid + ("1.1.1.dev1", 200, "2.2.2.dev1", "0.9.3"), + # server gives non-string type + (True, 200, "2.2.2", "2.2.2"), + ], +) +def test_gets_correct_snakebids_version( + build: BuildBackend, + server: Any, + server_status: str, + metadata: str, + expected: str, + mocker: MockerFixture, + tmp_path: Path, +): + tmpdir = Path(tempfile.mkdtemp(dir=tmp_path)) + with requests_mock.Mocker() as m: + m.get( + "https://pypi.org/pypi/snakebids/json", + json={"info": {"version": server}}, + status_code=server_status, + ) + metadata_patch = mocker.patch("importlib.metadata.version") + metadata_patch.return_value = metadata + data = get_empty_data("testapp", build) + copier.run_copy( + str(Path(itx.first(snakebids.__path__), "project_template")), + tmpdir / data["app_full_name"], + data=data, + unsafe=True, + ) + with open(tmpdir / data["app_full_name"] / "pyproject.toml", "rb") as f: + pyproject = tomllib.load(f) + if build == "poetry": + assert ( + pyproject["tool"]["poetry"]["dependencies"]["snakebids"] == f">={expected}" + ) + else: + assert f"snakebids >= {expected}" in pyproject["project"]["dependencies"] + + +@given( + name=st.text() + .filter(lambda s: not re.match(r"^[a-zA-Z_][a-zA-Z_0-9]*$", s)) + .filter(lambda s: pathvalidate.is_valid_filename(s, pathvalidate.Platform.LINUX)) +) +@allow_function_scoped +def test_invalid_app_name_raises_error(name: str, tmp_path: Path): + data = get_empty_data(name, "setuptools") + with pytest.raises(prompt_toolkit.validation.ValidationError): + copier.run_copy( + str(Path(itx.first(snakebids.__path__), "project_template")), + tmp_path / data["app_full_name"], + data=data, + unsafe=True, + ) + + +@pytest.mark.parametrize( + ["build", "build_backend"], + [ + ("poetry", "poetry.core.masonry.api"), + ("hatch", "hatchling.build"), + ("flit", "flit_core.buildapi"), + ("setuptools", "setuptools.build_meta"), + ], +) +def test_correct_build_system_used( + tmp_path: Path, build: BuildBackend, build_backend: str +): + tmpdir = Path(tempfile.mkdtemp(dir=tmp_path)) + data = get_empty_data("testapp", build) + copier.run_copy( + str(Path(itx.first(snakebids.__path__), "project_template")), + tmpdir / data["app_full_name"], + data=data, + unsafe=True, + ) + with open(tmpdir / data["app_full_name"] / "pyproject.toml", "rb") as f: + pyproject = tomllib.load(f) + assert pyproject["build-system"]["build-backend"] == build_backend + + +@given( + full_name=st.text(), + email=st.emails() | st.just(""), + app_full_name=st.from_regex(r"[a-zA-Z_][a-zA-Z_0-9]*", fullmatch=True), + github=st.text(), + app_description=st.text(), + app_version=st.text(min_size=1), + create_doc_template=st.just(False), + license=st.text(), +) +@settings(suppress_health_check=[HealthCheck.function_scoped_fixture], deadline=1000) +@pytest.mark.parametrize("build", BUILD_BACKENDS) +def test_pyproject_correctly_formatted( + tmp_path: Path, build: BuildBackend, **kwargs: Unpack[DataFields] +): + tmpdir = Path(tempfile.mkdtemp(dir=tmp_path)) + kwargs["build_system"] = build + copier.run_copy( + str(Path(itx.first(snakebids.__path__), "project_template")), + tmpdir / kwargs["app_full_name"], + data=kwargs, + unsafe=True, + ) + with open(tmpdir / kwargs["app_full_name"] / "pyproject.toml", "rb") as f: + pyproject = tomllib.load(f) + if build == "poetry": + assert kwargs["app_full_name"] == pyproject["tool"]["poetry"]["name"] + assert kwargs["app_version"] == pyproject["tool"]["poetry"]["version"] + assert kwargs["app_description"] == pyproject["tool"]["poetry"]["description"] + if kwargs["license"]: + assert kwargs["license"] == pyproject["tool"]["poetry"]["license"] + else: + assert "license" not in pyproject["tool"]["poetry"] + if kwargs["full_name"]: + assert len(pyproject["tool"]["poetry"]["authors"]) == 1 + email_tag = f" <{kwargs['email']}>" if kwargs["email"] else "" + assert ( + f'{kwargs["full_name"]}{email_tag}' + == pyproject["tool"]["poetry"]["authors"][0] + ) + else: + assert "authors" not in pyproject["tool"]["poetry"] + return + + assert kwargs["app_full_name"] == pyproject["project"]["name"] + assert kwargs["app_version"] == pyproject["project"]["version"] + assert kwargs["app_description"] == pyproject["project"]["description"] + if kwargs["license"]: + assert kwargs["license"] == pyproject["project"]["license"] + else: + assert "license" not in pyproject["project"] + if kwargs["full_name"] or kwargs["email"]: + assert len(pyproject["project"]["authors"]) == 1 + author_obj: dict[str, str] = {} + if kwargs["full_name"]: + author_obj["name"] = kwargs["full_name"] + if kwargs["email"]: + author_obj["email"] = kwargs["email"] + assert author_obj == pyproject["project"]["authors"][0] + else: + assert "authors" not in pyproject["project"] + + +@needs_docker(f"snakebids/test-template:{platform.python_version()}") +@pytest.mark.parametrize( + ["build", "venv"], + [ + ("setuptools", "setuptools"), + ("poetry", "poetry"), + ("hatch", "hatch"), + ("flit", "pdm"), + ], +) +def test_template_dry_runs_successfully(tmp_path: Path, build: BuildBackend, venv: str): app_name = "snakebids_app" - cookiecutter( - join(itx.first(snakebids.__path__), "project_template"), - no_input=True, - output_dir=str(tmp_path), + data = get_empty_data(app_name, build) + + copier.run_copy( + str(Path(itx.first(snakebids.__path__), "project_template")), + tmp_path / app_name, + data=data, + unsafe=True, ) - app = SnakeBidsApp( - tmp_path / app_name / app_name, - args=SnakebidsArgs( - force=False, - outputdir=tmp_path / "out", - snakemake_args=["-n"], - args_dict={ - "bids_dir": Path("snakebids") / "tests" / "data" / "bids_bold", - "output_dir": tmp_path / "out", - "analysis_level": "participant", - "smoothing_fwhm": "1", - "filter_bold": None, - "wildcards_bold": None, - "path_bold": None, - "participant_label": None, - "exclude_participant_label": None, - "plugins.validator.skip": True, - }, - ), + cmd = sp.run( + [ + "docker", + "run", + "-v", + f"{tmp_path / app_name}:/app", + "--rm", + f"snakebids/test-template:{platform.python_version()}", + venv, + app_name, + ], + capture_output=True, + check=False, ) - with pytest.raises(SystemExit) as err: - app.run_snakemake() - assert err.value.code == 0 + try: + cmd.check_returncode() + except Exception as err: + print(cmd.stdout) + print(cmd.stderr, file=sys.stderr) + raise err + assert "All set" in cmd.stdout.decode() diff --git a/snakebids/tests/test_validate_plugin.py b/snakebids/tests/test_validate_plugin.py index 5c13e743..b469f1b2 100644 --- a/snakebids/tests/test_validate_plugin.py +++ b/snakebids/tests/test_validate_plugin.py @@ -35,7 +35,7 @@ def test_validation_successful(self, app: SnakeBidsApp, mocker: MockerFixture): # Test successful validation mocker.patch("subprocess.check_call", return_value=0) - app.config["bids_dirs"] = "path/to/bids/dir" + app.config["bids_dir"] = "path/to/bids/dir" app.config["plugins.validator.skip"] = False validator = BidsValidator() @@ -48,7 +48,7 @@ def test_missing_bids_validator( # Test fall back to Pybids validation mocker.patch("subprocess.check_call", side_effect=FileNotFoundError) - app.config["bids_dirs"] = "path/to/bids/dir" + app.config["bids_dir"] = "path/to/bids/dir" app.config["plugins.validator.skip"] = False validator = BidsValidator() @@ -68,7 +68,7 @@ def test_raise_validation_error(self, app: SnakeBidsApp, mocker: MockerFixture): "subprocess.check_call", side_effect=subprocess.CalledProcessError(1, "") ) - app.config["bids_dirs"] = "path/to/bids/dir" + app.config["bids_dir"] = "path/to/bids/dir" app.config["plugins.validator.skip"] = False # Check error raised @@ -85,7 +85,7 @@ def test_ignore_validation_error(self, app: SnakeBidsApp, mocker: MockerFixture) "subprocess.check_call", side_effect=subprocess.CalledProcessError(1, "") ) - app.config["bids_dirs"] = "path/to/bids/dir" + app.config["bids_dir"] = "path/to/bids/dir" app.config["plugins.validator.skip"] = False # Check if error is skipped on invalid diff --git a/typings/copier.pyi b/typings/copier.pyi new file mode 100644 index 00000000..7bcf5ae8 --- /dev/null +++ b/typings/copier.pyi @@ -0,0 +1,31 @@ +from os import PathLike +from typing import Any, AnyStr, Literal, Mapping, TypedDict + +from git import Sequence +from typing_extensions import TypeAlias, Unpack + +AnyPath: TypeAlias = "AnyStr | PathLike[AnyStr]" + +class CopierArgs(TypedDict, total=False): + answers_file: AnyPath[str] | AnyPath[bytes] + vcs_ref: str | None + exclude: Sequence[str] + use_prereleases: bool + skip_if_exists: Sequence[str] + cleanup_on_error: bool + defaults: bool + user_defaults: dict[str, Any] + overwrite: bool + pretend: bool + quiet: bool + conflict: Literal["inline", "rej"] + context_lines: int + unsafe: bool + skip_answered: bool + +def run_copy( + src_path: str, + dst_path: AnyPath[str] | AnyPath[bytes] = ..., + data: Mapping[str, Any] | None = ..., + **kwargs: Unpack[CopierArgs] +) -> None: ...