From dab0d06d59c4448bd5f1fa58b918960264d4609a Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Tue, 23 Dec 2025 11:49:39 +1000 Subject: [PATCH 01/34] Move from pip to uv --- .dockerignore | 2 + docker-compose.yml | 2 - docker/dev/Dockerfile | 67 +- docker/production/Dockerfile | 90 +- docs/setup/osx.md | 21 +- docs/setup/windows.md | 61 +- pyproject.toml | 96 +- rdrf/setup.py | 104 -- requirements/clients | 1 - requirements/dev-requirements.txt | 7 - requirements/requirements.txt | 43 - requirements/test-requirements.txt | 16 - uv.lock | 2464 ++++++++++++++++++++++++++++ 13 files changed, 2663 insertions(+), 311 deletions(-) delete mode 100644 rdrf/setup.py delete mode 120000 requirements/clients delete mode 100644 requirements/dev-requirements.txt delete mode 100644 requirements/requirements.txt delete mode 100644 requirements/test-requirements.txt create mode 100644 uv.lock diff --git a/.dockerignore b/.dockerignore index e5f70c591..143424bfb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,6 @@ .git +.venv +__pycache__ virt_* docs *.pyc diff --git a/docker-compose.yml b/docker-compose.yml index 5f8da5165..a29eeb5f4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.7" - volumes: dev_db_data: dev_clinicaldb_data: diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index 8d9d74ccc..a5a213144 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -1,10 +1,12 @@ -# FROM muccg/rdrf-builder -FROM python:3.13 as builder +# Builder stage +FROM python:3.13 AS builder -ENV PYTHONUNBUFFERED 1 +ENV PYTHONUNBUFFERED=1 + +# Install uv +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ RUN apt-get update && apt-get install -y --no-install-recommends \ - # TODO check if requirements are needed # Base gettext \ libpq5 \ @@ -22,43 +24,36 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ zlib1g-dev \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN mkdir -p /requirements -WORKDIR /requirements - -# RUN env | sort - -# Add our python deps in multiple docker layers -# hgvs was failing due to lack of nose, hence the order - -COPY requirements/* ./ +WORKDIR /app +# Copy dependency files first for layer caching +COPY pyproject.toml uv.lock ./ COPY clients ./clients -RUN --mount=type=cache,target=/root/.cache/pip \ - pip install --upgrade pip setuptools && \ - pip install -r requirements.txt && \ - pip install -r dev-requirements.txt && \ - pip install -r test-requirements.txt +# Sync dependencies to /opt/venv (outside /app which gets volume-mounted in dev) +ENV UV_PROJECT_ENVIRONMENT=/opt/venv +ENV UV_LINK_MODE=copy +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --locked --no-install-project --all-extras VOLUME ["/data"] +# Runtime stage FROM python:3.13-slim +# Install uv +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ + ENV PYTHONPATH="/app/rdrf/:${PYTHONPATH}" -ENV DJANGO_SETTINGS_MODULE rdrf.settings +ENV DJANGO_SETTINGS_MODULE=rdrf.settings ENV STATIC_ROOT="/data/static" ENV WRITABLE_DIRECTORY="/data/scratch" ENV LOCALE_PATHS="/app/translations/locale" ENV LOG_DIRECTORY="/data/log" ENV MEDIA_ROOT="/data/static/media" -# RUN apt-get update && apt-get install -y --no-install-recommends \ -# libxml2 \ -# && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - RUN apt-get update && apt-get install -y --no-install-recommends \ # Base - # TODO check if requirements are needed gettext \ libpq5 \ media-types \ @@ -71,17 +66,23 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ git \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN mkdir /requirements -WORKDIR /requirements +# Copy venv from builder to /opt/venv +COPY --from=builder /opt/venv /opt/venv -COPY --from=builder /requirements/ . +WORKDIR /app + +# Copy dependency files +COPY pyproject.toml uv.lock ./ +COPY clients ./clients -RUN --mount=type=cache,target=/root/.cache/pip \ - pip install -r requirements.txt && \ - pip install -r dev-requirements.txt && \ - pip install -r test-requirements.txt +# Finalize dependency install +ENV UV_PROJECT_ENVIRONMENT=/opt/venv +ENV UV_LINK_MODE=copy +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --locked --all-extras -RUN rm -Rf /root/.cache +# Add venv to PATH +ENV PATH="/opt/venv/bin:$PATH" COPY docker/dev/docker-entrypoint.sh / RUN chmod +x /docker-entrypoint.sh @@ -91,7 +92,7 @@ RUN chmod +x /aws-lambda-rie VOLUME ["/app", "/data"] -ENV HOME /data +ENV HOME=/data WORKDIR /data EXPOSE 8000 diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index 68652cd8d..2008ee1ef 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -1,10 +1,12 @@ -# Container to build our prod image -FROM python:3.13 as builder +# Builder stage +FROM python:3.13 AS builder -ENV PYTHONUNBUFFERED 1 +ENV PYTHONUNBUFFERED=1 + +# Install uv +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ RUN apt-get update && apt-get install -y --no-install-recommends \ - # TODO check if requirements are needed # Base gettext \ libpq5 \ @@ -20,43 +22,40 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libyaml-dev \ unixodbc-dev \ zlib1g-dev \ - unixodbc-dev \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN mkdir -p /requirements -WORKDIR /requirements - -# RUN env | sort - -# Add our python deps in multiple docker layers -# hgvs was failing due to lack of nose, hence the order - -COPY requirements/* ./ +WORKDIR /app +# Copy dependency files first for layer caching +COPY pyproject.toml uv.lock ./ COPY clients ./clients -RUN pip install --upgrade setuptools pip -RUN pip install -r requirements.txt +# Sync production dependencies only +ENV UV_LINK_MODE=copy +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --locked --no-install-project --no-dev -# Actual image we are building +# Runtime stage FROM python:3.13-slim -ENV PYTHONUNBUFFERED 1 +ENV PYTHONUNBUFFERED=1 + +# Install uv +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ ENV PYTHONPATH="/app/rdrf/" -ENV DJANGO_SETTINGS_MODULE rdrf.settings - -ENV PROJECT_NAME trrf -ENV PROJECT_SOURCE https://github.com/eresearchqut/trrf.git -ENV DEPLOYMENT prod -ENV PRODUCTION 1 -ENV DEBUG 0 -ENV STATIC_ROOT /data/static -ENV WRITABLE_DIRECTORY /data/scratch -ENV MEDIA_ROOT /data/static/media -ENV LOG_DIRECTORY /data/log -ENV LOCALE_PATHS /data/translations/locale -ENV DJANGO_SETTINGS_MODULE rdrf.settings +ENV DJANGO_SETTINGS_MODULE=rdrf.settings + +ENV PROJECT_NAME=trrf +ENV PROJECT_SOURCE=https://github.com/eresearchqut/trrf.git +ENV DEPLOYMENT=prod +ENV PRODUCTION=1 +ENV DEBUG=0 +ENV STATIC_ROOT=/data/static +ENV WRITABLE_DIRECTORY=/data/scratch +ENV MEDIA_ROOT=/data/static/media +ENV LOG_DIRECTORY=/data/log +ENV LOCALE_PATHS=/data/translations/locale RUN mkdir /app @@ -68,7 +67,6 @@ RUN addgroup --gid 1000 django \ RUN apt-get update && apt-get install -y --no-install-recommends \ # Base - # TODO check if requirements are needed git \ gettext \ libpq5 \ @@ -80,43 +78,43 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN mkdir /requirements -WORKDIR /requirements +WORKDIR /app -COPY --from=builder /root/.cache /root/.cache -COPY --from=builder /requirements/requirements.txt . +# Copy venv from builder +COPY --from=builder /app/.venv /app/.venv +# Copy dependency files +COPY pyproject.toml uv.lock ./ COPY clients ./clients -RUN pip install -r requirements.txt +# Finalize dependency install (production only) +ENV UV_LINK_MODE=copy +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --locked --no-dev + +# Add venv to PATH +ENV PATH="/app/.venv/bin:$PATH" -# The generate snakeoil cert is valid for 10 years, but if you need to +# The generated snakeoil cert is valid for 10 years, but if you need to # re-generate it you can use: # RUN make-ssl-cert generate-default-snakeoil --force-overwrite RUN chgrp -R django /etc/ssl/private/ \ && chmod g+r /etc/ssl/private/ssl-cert-snakeoil.key -RUN rm -Rf /root/.cache - # Currently just using the dev entrypoint for prod as well -# TODO separate or move one level up COPY docker/dev/docker-entrypoint.sh / RUN chmod +x /docker-entrypoint.sh VOLUME ["/data"] -ENV HOME /data +ENV HOME=/data EXPOSE 9000 COPY --chown=django:django . /app -# RUN chown -R django /app - -# COPY --from=nodebuilder /app/root/.cache /root/.cache USER django WORKDIR /data ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["uwsgi"] - diff --git a/docs/setup/osx.md b/docs/setup/osx.md index 1437610f0..7b8c4022d 100644 --- a/docs/setup/osx.md +++ b/docs/setup/osx.md @@ -7,8 +7,7 @@ A guide to setting up your OSX environment for developing on the Mac Docker -> https://www.docker.com/ (download, create a docker account and login) XCode -> install from app store (make sure you open and agree to licence) Brew -> /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - pyenv -> https://github.com/pyenv/pyenv - pyenv-virtualenv -> https://github.com/pyenv/pyenv-virtualenv + uv -> curl -LsSf https://astral.sh/uv/install.sh | sh ### Dependencies @@ -17,19 +16,9 @@ A guide to setting up your OSX environment for developing on the Mac brew install unixodbc -### Python - - pyenv init - pyenv install 3.9.0 - pyenv global 3.9.0 - pyenv virtualenv 3.9.0 trrf-dev - pyenv shell trrf-dev - pip install --upgrade pip - - - ### Installing modules for local development - pip install -r requirements/requirements.txt - pip install -r requirements/dev-requirements.txt - pip install -r requirements/test-requirements.txt + cd /path/to/trrf + uv sync --all-extras + +This will create a virtual environment in `.venv` and install all dependencies. diff --git a/docs/setup/windows.md b/docs/setup/windows.md index 7dda51ce4..5e41ab57c 100644 --- a/docs/setup/windows.md +++ b/docs/setup/windows.md @@ -42,39 +42,27 @@ Running Launch from the Microsoft Store once it has downloaded will install it. 5. Update packages: `sudo apt update -y` -6. Install pyenv - * Go to https://github.com/pyenv/pyenv#installation - * Under pre-requisites, follow the link to install the Python build dependencies first - * Use the `The automatic installer` instructions for installation of pyenv - * Confirm it's working by running `pyenv`. If this doesn't work you'll need to add `$HOME/.pyenv/bin` to your PATH in your WSL - * Follow the instructions output by `pyenv init` - -7. Install python. Check the current python version in the `Dockerfile`. +6. Install uv (Python package manager) ```shell - pyenv global 3.9 + curl -LsSf https://astral.sh/uv/install.sh | sh ``` - Confirm it's working: `python --version` -8. Configure Git + Restart your shell or run `source ~/.local/bin/env` to add uv to your PATH. + +7. Configure Git * Configure your Git client, as desired, on your WSL distribution * Clone the trrf repo into your WSL to an unmounted directory. N.B Cloning to a mounted windows directory will cause significant performance issues! -9. Configure TRRF virtual python environment. - ```shell - pyenv virtualenv 3.9 trrf - pyenv shell trrf - ``` -10. Install pre-requisite packages +8. Install pre-requisite packages Note: these packages are specific to Ubuntu and may differ if you've installed a different distribution. ```shell sudo apt install postgresql-client libpq-dev unixodbc-dev ``` -11. Install project dependencies +9. Install project dependencies ```shell cd /path/to/trrf - pip install -r requirements/requirements.txt - pip install -r requirements/dev-requirements.txt - pip install -r requirements/test-requirements.txt + uv sync --all-extras ``` + This will create a virtual environment in `.venv` and install all dependencies. ### Run TRRF locally @@ -101,7 +89,7 @@ Running Launch from the Microsoft Store once it has downloaded will install it. ### General development setup 1. Open the `trrf` project, selecting the cloned repo within the wsl directory structure 2. Setup WSL as the Python interpreter: https://www.jetbrains.com/help/pycharm/using-wsl-as-a-remote-interpreter.html#configure-wsl - * Python executable path - select the python executable in the virtual environment you created for trrf. e.g. `/home/totagian/.pyenv/versions/trrf/bin/python`. + * Python executable path - select the python executable in the `.venv` directory. e.g. `/path/to/trrf/.venv/bin/python`. 3. Enable Django support: 1. File > Settings > Languages and Frameworks > Enable Django Support * Django project root: `\\wsl$\Ubuntu-20.04\path\to\trrf\rdrf` @@ -132,25 +120,14 @@ Running Launch from the Microsoft Store once it has downloaded will install it. git submodule init git submodule update ``` -2. Create a virtual environment using WLS and pyenv - ``` - pyenv virtualenv mnd - pyenv shell mnd +2. Install the python dependencies using uv ``` -3. Install the python lib dependencies - ``` - cd path/to/mnd/rdrf/requirements - - pip install -r requirements.txt - pip install -r dev-requirements.txt - pip install -r test-requirements.txt - - cd path/to/mnd/requirements - - pip install -r requirements.txt - pip install -r dev-requirements.txt - pip install -r test-requirements.txt + cd path/to/mnd/rdrf + uv sync --all-extras + + cd path/to/mnd + uv sync --all-extras ``` -4. Configure the python interpreter in IntelliJ using wsl as the interpreter - * Python Interpreter path needs to point to the python exe in the virtual environment you created for this site. - e.g. `/home/totagian/.pyenv/versions/mnd/bin/python` +3. Configure the python interpreter in IntelliJ using wsl as the interpreter + * Python Interpreter path needs to point to the python exe in the `.venv` directory. + e.g. `/path/to/mnd/.venv/bin/python` diff --git a/pyproject.toml b/pyproject.toml index 047f07d38..80d1efc6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,97 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "trrf" +version = "1.0.0" +description = "Trial Ready Registry Framework" +authors = [{ name = "Queensland University of Technology - eResearch" }] +requires-python = ">=3.13" +dependencies = [ + "ccg-django-utils==0.4.2", + "Django==4.2.27", + "django-anymail==8.5", + "django-countries==7.2.1", + "django-csp==3.7", + "django-extensions==3.2.1", + "django-registration-redux==2.10", + "djangorestframework==3.15.2", + "django-storages==1.14.6", + "django-stronghold==0.4.0", + "jsonschema==4.4.0", + "openpyxl==3.0.9", + "psycopg2-binary==2.9.10", + "pycountry==22.1.10", + "python-dateutil==2.8.2", + "python-magic==0.4.24", + "pyyaml==6.0.3", + "six==1.16.0", + "SQLAlchemy==1.3.24", + "uwsgi==2.0.30", + "django-formtools==2.3", + "django-otp==1.1.3", + "django-two-factor-auth==1.15.5", + "phonenumberslite==8.12.39", + "Pillow==11.3.0", + "qrcode==6.1", + "django-reversion==5.0.0", + "ua-parser==0.10.0", + "user-agents==2.2.0", + "django-user-agents==0.4.0", + "django-simple-history==3.0.0", + "lark==1.0.0", + "boto3==1.40.41", + "aws-xray-sdk==2.9.0", + "graphene-django==3.1.5", + "django-filter==21.1", + "flatten_json==0.1.13", + "gql-query-builder @ git+https://github.com/eresearchqut/gql-query-builder@a983448", + "awslambdaric==3.1.1", + "django-cache-memoize==0.1.10", + "openapi-client", + "langcodes==3.3.0", + "language_data==1.3", +] + +[project.optional-dependencies] +dev = [ + "sphinx", + "sphinxcontrib-fulltoc", + "Werkzeug==3.1.4", + "python-Levenshtein", + "ipython", + "django-silk==4.4.0", + "ruff", +] +test = [ + "sure==1.4.11", + "django-nose==1.4.7", + "pytest==7.1.1", + "pytest-django==4.5.2", + "pynose==1.5.5", + "nose-timer==0.7.5", + "aloe==0.2.0", + "aloe_webdriver==0.6.0", + "aloe_django==0.2.0", + "pyvirtualdisplay==0.2.5", + "selenium==4.1.3", + "unittest-xml-reporting==3.2.0", + "requests==2.32.4", + "sqlalchemy-utils==0.36.1", + "stellar==0.4.5", + "coverage==5.5", +] + +[tool.uv.sources] +openapi-client = { path = "./clients/xnat/generated" } + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["rdrf", "registry", "report", "useraudit"] + [tool.ruff] line-length = 80 exclude = [ @@ -18,4 +112,4 @@ exclude = [ ] [tool.ruff.format] -quote-style = "double" \ No newline at end of file +quote-style = "double" diff --git a/rdrf/setup.py b/rdrf/setup.py deleted file mode 100644 index baf687390..000000000 --- a/rdrf/setup.py +++ /dev/null @@ -1,104 +0,0 @@ -import os - -from setuptools import find_packages, setup - -package_data = {} -start_dir = os.getcwd() - - -def add_file_for_package(package, subdir, f): - full_path = os.path.join(subdir, f) - # print "%s: %s" % (package, full_path) - return full_path - - -packages = [ - "rdrf", - "rdrf.account_handling", - "rdrf.auth", - "rdrf.context_processors", - "rdrf.db", - "rdrf.events", - "rdrf.forms", - "rdrf.forms.dynamic", - "rdrf.forms.fields", - "rdrf.forms.navigation", - "rdrf.forms.progress", - "rdrf.forms.validation", - "rdrf.forms.widgets", - "rdrf.helpers", - "rdrf.models", - "rdrf.models.definition", - "rdrf.reports", - "rdrf.routing", - "rdrf.security", - "rdrf.services", - "rdrf.services.io", - "rdrf.services.io.content", - "rdrf.services.io.content.export_import", - "rdrf.services.io.defs", - "rdrf.services.io.notifications", - "rdrf.services.rest", - "rdrf.services.rest.urls", - "rdrf.services.rest.views", - "rdrf.services.rpc", - "rdrf.testing", - "rdrf.testing.behaviour", - "rdrf.testing.unit", - "rdrf.views", - "rdrf.views.decorators", - "rdrf.workflows", - "registry", - "registry.common", - "registry.patients", - "registry.groups", - "report", -] - -for package in [ - "rdrf", - "registry.common", - "registry.groups", - "registry.patients", - "registry.humangenome", - "report", -]: - package_data[package] = [] - if "." in package: - base_dir, package_dir = package.split(".") - os.chdir(os.path.join(start_dir, base_dir, package_dir)) - else: - base_dir = package - os.chdir(os.path.join(start_dir, base_dir)) - - for data_dir in ( - "templates", - "static", - "migrations", - "fixtures", - "features", - "schemas", - "templatetags", - "management", - ): - package_data[package].extend( - [ - add_file_for_package(package, subdir, f) - for (subdir, dirs, files) in os.walk(data_dir) - for f in files - ] - ) - - os.chdir(start_dir) - - -setup( - name="trrf", - version="1.0.0", - packages=find_packages(), - description="TRRF", - long_description="Trial Ready Registry Framework", - author="Queensland University of Technology - eResearch", - package_data=package_data, - zip_safe=False, -) diff --git a/requirements/clients b/requirements/clients deleted file mode 120000 index 4d613f769..000000000 --- a/requirements/clients +++ /dev/null @@ -1 +0,0 @@ -../clients \ No newline at end of file diff --git a/requirements/dev-requirements.txt b/requirements/dev-requirements.txt deleted file mode 100644 index 07501dc0b..000000000 --- a/requirements/dev-requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -sphinx -sphinxcontrib-fulltoc -Werkzeug==3.1.4 -python-Levenshtein -ipython -django-silk==4.4.0 -ruff \ No newline at end of file diff --git a/requirements/requirements.txt b/requirements/requirements.txt deleted file mode 100644 index 8794f72d6..000000000 --- a/requirements/requirements.txt +++ /dev/null @@ -1,43 +0,0 @@ -ccg-django-utils==0.4.2 -Django==4.2.27 -django-anymail==8.5 -django-countries==7.2.1 -django-csp==3.7 -django-extensions==3.2.1 -django-registration-redux==2.10 -djangorestframework==3.15.2 -django-storages==1.14.6 -django-stronghold==0.4.0 -jsonschema==4.4.0 -openpyxl==3.0.9 -psycopg2-binary==2.9.10 -pycountry==22.1.10 -python-dateutil==2.8.2 -python-magic==0.4.24 -pyyaml==6.0.3 -six==1.16.0 -SQLAlchemy==1.3.24 -uwsgi==2.0.30 -django-formtools==2.3 -django-otp==1.1.3 -django-two-factor-auth==1.15.5 -phonenumberslite==8.12.39 -Pillow==11.3.0 -qrcode==6.1 -django-reversion==5.0.0 -ua-parser==0.10.0 -user-agents==2.2.0 -django-user-agents==0.4.0 -django-simple-history==3.0.0 -lark==1.0.0 -boto3==1.40.41 -aws-xray-sdk==2.9.0 -graphene-django==3.1.5 -django-filter==21.1 -flatten_json==0.1.13 -gql-query-builder @ git+https://github.com/eresearchqut/gql-query-builder@a983448 -awslambdaric==3.1.1 -django-cache-memoize==0.1.10 -./clients/xnat/generated -langcodes==3.3.0 -language_data==1.3 diff --git a/requirements/test-requirements.txt b/requirements/test-requirements.txt deleted file mode 100644 index a140b4873..000000000 --- a/requirements/test-requirements.txt +++ /dev/null @@ -1,16 +0,0 @@ -sure==1.4.11 -django-nose==1.4.7 -pytest==7.1.1 -pytest-django==4.5.2 -pynose==1.5.5 -nose-timer==0.7.5 -aloe==0.2.0 -aloe_webdriver==0.6.0 -aloe_django==0.2.0 -pyvirtualdisplay==0.2.5 -selenium==4.1.3 -unittest-xml-reporting==3.2.0 -requests==2.32.4 -sqlalchemy-utils==0.36.1 -stellar==0.4.5 -coverage==5.5 diff --git a/uv.lock b/uv.lock new file mode 100644 index 000000000..e3f804b5b --- /dev/null +++ b/uv.lock @@ -0,0 +1,2464 @@ +version = 1 +revision = 3 +requires-python = ">=3.13" + +[[package]] +name = "alabaster" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, +] + +[[package]] +name = "aloe" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ansicolors" }, + { name = "colorama" }, + { name = "gherkin-official" }, + { name = "nose" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/43/f64222832386b8dc31078086aa157ba67581275630974a204f3df52da56e/aloe-0.2.0.tar.gz", hash = "sha256:d73f69d933600f3ba20c6773df485cc42b5b2e8c274fa3f6798750aedbaf5aa2", size = 97193, upload-time = "2020-01-12T04:58:52.558Z" } + +[[package]] +name = "aloe-django" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aloe" }, + { name = "cssselect" }, + { name = "django" }, + { name = "django-nose" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7f/d5/e28852bfb63e12478a488e165750cc33fb526dea6b14f8cd1a12f1577078/aloe_django-0.2.0.tar.gz", hash = "sha256:004e752cca48155ed249433a8af9cface938c62d903579e5a722f3bce62ba410", size = 44066, upload-time = "2020-01-12T10:56:14.02Z" } + +[[package]] +name = "aloe-webdriver" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aloe" }, + { name = "selenium" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/30/9cfe29e598b95ed3aa892b5dbf191e1b2c4e4ac692169fe29624f5fed448/aloe_webdriver-0.6.0.tar.gz", hash = "sha256:3b4f8ddd73d4c0ebf6afcabcb35283fe676ce9a4c5f4f0c038b0f16855a1a6d3", size = 36551, upload-time = "2020-01-12T22:35:58.849Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/1a/1462553bb538cf01aba6ba8d598638d8c084cfd49ca98a72f6bb51c96168/aloe_webdriver-0.6.0-py3-none-any.whl", hash = "sha256:3875e87223d68a4e06488fe67c2cd81f40d1bbb0faa3417434659916bd570072", size = 32087, upload-time = "2020-01-12T22:35:56.925Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "ansicolors" +version = "1.1.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/31/7faed52088732704523c259e24c26ce6f2f33fbeff2ff59274560c27628e/ansicolors-1.1.8.zip", hash = "sha256:99f94f5e3348a0bcd43c82e5fc4414013ccc19d70bd939ad71e0133ce9c372e0", size = 23027, upload-time = "2017-06-02T21:22:10.729Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/18/a56e2fe47b259bb52201093a3a9d4a32014f9d85071ad07e9d60600890ca/ansicolors-1.1.8-py2.py3-none-any.whl", hash = "sha256:00d2dde5a675579325902536738dd27e4fac1fd68f773fe36c21044eb559e187", size = 13847, upload-time = "2017-06-02T21:22:12.67Z" }, +] + +[[package]] +name = "asgiref" +version = "3.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/b9/4db2509eabd14b4a8c71d1b24c8d5734c52b8560a7b1e1a8b56c8d25568b/asgiref-3.11.0.tar.gz", hash = "sha256:13acff32519542a1736223fb79a715acdebe24286d98e8b164a73085f40da2c4", size = 37969, upload-time = "2025-11-19T15:32:20.106Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/be/317c2c55b8bbec407257d45f5c8d1b6867abc76d12043f2d3d58c538a4ea/asgiref-3.11.0-py3-none-any.whl", hash = "sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d", size = 24096, upload-time = "2025-11-19T15:32:19.004Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "atomicwrites" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/87/c6/53da25344e3e3a9c01095a89f16dbcda021c609ddb42dd6d7c0528236fb2/atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11", size = 14227, upload-time = "2022-07-08T18:31:40.459Z" } + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "autopep8" +version = "2.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycodestyle" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/d8/30873d2b7b57dee9263e53d142da044c4600a46f2d28374b3e38b023df16/autopep8-2.3.2.tar.gz", hash = "sha256:89440a4f969197b69a995e4ce0661b031f455a9f776d2c5ba3dbd83466931758", size = 92210, upload-time = "2025-01-14T14:46:18.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl", hash = "sha256:ce8ad498672c845a0c3de2629c15b635ec2b05ef8177a6e7c91c74f3e9b51128", size = 45807, upload-time = "2025-01-14T14:46:15.466Z" }, +] + +[[package]] +name = "aws-xray-sdk" +version = "2.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "future" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/26/927206007f1ac57b0801046dc9baed8df9ccbdc7622b79bdaf0c193e8051/aws-xray-sdk-2.9.0.tar.gz", hash = "sha256:b0cd972db218d4d8f7b53ad806fc6184626b924c4997ae58fc9f2a8cd1281568", size = 71968, upload-time = "2021-12-06T20:55:24.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/4b/4e0b47146a3fdca48b00774b7280e35c48c48aa9960010c6fc4a3f7f49ad/aws_xray_sdk-2.9.0-py2.py3-none-any.whl", hash = "sha256:98216b3ac8281b51b59a8703f8ec561c460807d9d0679838f5c0179d381d7e58", size = 98902, upload-time = "2021-12-06T20:56:12.011Z" }, +] + +[[package]] +name = "awslambdaric" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "simplejson" }, + { name = "snapshot-restore-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/25/9ae3c97af6dc4628cf8094dd2189a8b97388409870fba1c54f58c64d5766/awslambdaric-3.1.1.tar.gz", hash = "sha256:1c1fd30570b9a2c5cc4ccd2151c883312c5eef2dbf759c8e9d29c18cec6de2e8", size = 4500924, upload-time = "2025-05-27T16:06:05.241Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/8c/24cd782cb5406bea659a386b8edf48d35c7ded88a7f30df533da96664eac/awslambdaric-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bb003f14f3754a3d6912e3a478cf3a306b84febdc26b612fe23c1143a89f0fd", size = 343077, upload-time = "2025-05-27T16:05:53.286Z" }, + { url = "https://files.pythonhosted.org/packages/c4/de/d8901e24e5a4852c3f88b7e3abaf897b1473ca00d1952100ff1cfa5ba500/awslambdaric-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:755db7118d1ed900a675a2608ea9c48c463949ede5cc91648c542a5ec89df4ed", size = 345680, upload-time = "2025-05-27T16:06:02.291Z" }, + { url = "https://files.pythonhosted.org/packages/a9/35/0e97e4cc862f586211b22d3cbb070e9d9a8c1646aaa5a38b5a530192805c/awslambdaric-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889b4bb6e9d88aab26d67cce7f9212aafa1f53c64eca2dc83cdf42a79eb3e6ec", size = 344893, upload-time = "2025-05-27T16:05:54.545Z" }, + { url = "https://files.pythonhosted.org/packages/79/10/2cc723ad18b3bd049af5175bf620262bedc0c788433c3e2e90e67ec3d16e/awslambdaric-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4972127ef34729c44c9567148e68a4eacc283d685400f9d08bf51138ac4ee3d5", size = 347136, upload-time = "2025-05-27T16:06:04.053Z" }, + { url = "https://files.pythonhosted.org/packages/06/b0/4acb191304bb2364c88984b09fa17b435575f7a1b50d9ada79038c5e7db0/awslambdaric-3.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:537e4986f723cb981af01d031743c9ae09b9ddc497d2582a548da0d696c81809", size = 343258, upload-time = "2025-05-27T16:05:55.76Z" }, + { url = "https://files.pythonhosted.org/packages/35/8d/7a39188d0e95fd9975deadeb56e4fba085b03a90c572a7cfa1f279b19e2d/awslambdaric-3.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5860d96e08cc4bab5bd4d7a2cd5eeb10ea17d0269fe4c1b7c57ac8d06abbf70", size = 345840, upload-time = "2025-05-27T16:06:06.102Z" }, + { url = "https://files.pythonhosted.org/packages/91/21/77c0d0867f263e270888c9c2fb85fa35e90b95d9d0cce32b252b3423c9c9/awslambdaric-3.1.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad2ff7352517b590ca5748f75b9b9df906b111139753f35bcb069f25c14d3c94", size = 344984, upload-time = "2025-05-27T16:05:56.978Z" }, + { url = "https://files.pythonhosted.org/packages/0e/6d/ad856d498a037b94a96866f22ce6f244fce73976f9c064cfbff5f5c94745/awslambdaric-3.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c8ecbcf05cf02f1bd263a0831b1acf3c29cd9296cb72e74067de71185f6c118", size = 347224, upload-time = "2025-05-27T16:06:08.408Z" }, +] + +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, +] + +[[package]] +name = "boto3" +version = "1.40.41" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "jmespath" }, + { name = "s3transfer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/52/f7/d652732fd8fc28f427f3e698e488b7422ede535fe4d813c7988642c7734b/boto3-1.40.41.tar.gz", hash = "sha256:2ea2463fc42812f3cab66b53114579b1f4b9a378ee48921d4385511a94307b24", size = 111621, upload-time = "2025-09-29T19:21:14.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/a8/d5c924e3dfce8804ff7119c1e84f423414851a82d30d744e81f4b61ddbff/boto3-1.40.41-py3-none-any.whl", hash = "sha256:02eac942aaa9f3a1c8a11f77e6f971b41c125973888f80f3eb177c2f21ad7a01", size = 139342, upload-time = "2025-09-29T19:21:12.728Z" }, +] + +[[package]] +name = "botocore" +version = "1.40.76" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/eb/50e2d280589a3c20c3b649bb66262d2b53a25c03262e4cc492048ac7540a/botocore-1.40.76.tar.gz", hash = "sha256:2b16024d68b29b973005adfb5039adfe9099ebe772d40a90ca89f2e165c495dc", size = 14494001, upload-time = "2025-11-18T20:22:59.131Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/6c/522e05388aa6fc66cf8ea46c6b29809a1a6f527ea864998b01ffb368ca36/botocore-1.40.76-py3-none-any.whl", hash = "sha256:fe425d386e48ac64c81cbb4a7181688d813df2e2b4c78b95ebe833c9e868c6f4", size = 14161738, upload-time = "2025-11-18T20:22:55.332Z" }, +] + +[[package]] +name = "ccg-django-utils" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a9/20/afdae4aa2a3e4fd97ca082f297053ded3526cd7e4ff70b649ef5c5761af7/ccg-django-utils-0.4.2.tar.gz", hash = "sha256:3942fabfdc9653965333ca2b6b3d5f752702b778cdccf46b88f2de5fc9492a76", size = 4696, upload-time = "2016-04-19T06:24:01.09Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/b7/cdab7617e6fe64d137a76ed790b2c1720d5643a28690a08a8fb5757dfe53/ccg_django_utils-0.4.2-py2.py3-none-any.whl", hash = "sha256:7e9842d82634c4e7d27af00b4848f9922b6c46c5b82192267e139389b7cdcd7c", size = 6861, upload-time = "2016-04-19T06:24:26.858Z" }, +] + +[[package]] +name = "certifi" +version = "2025.11.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "coverage" +version = "5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/38/df/d5e67851e83948def768d7fb1a0fd373665b20f56ff63ed220c6cd16cb11/coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c", size = 691258, upload-time = "2021-02-28T20:13:23.11Z" } + +[[package]] +name = "cryptography" +version = "46.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" }, + { url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" }, + { url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" }, + { url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" }, + { url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" }, + { url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" }, + { url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" }, + { url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" }, + { url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" }, + { url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" }, + { url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" }, + { url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" }, + { url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" }, + { url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" }, + { url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" }, + { url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" }, + { url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" }, + { url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" }, + { url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" }, + { url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" }, + { url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" }, + { url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" }, + { url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" }, + { url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" }, + { url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" }, + { url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" }, + { url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" }, + { url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" }, + { url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" }, + { url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" }, + { url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" }, + { url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" }, + { url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" }, + { url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" }, + { url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" }, +] + +[[package]] +name = "cssselect" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/0a/c3ea9573b1dc2e151abfe88c7fe0c26d1892fe6ed02d0cdb30f0d57029d5/cssselect-1.3.0.tar.gz", hash = "sha256:57f8a99424cfab289a1b6a816a43075a4b00948c86b4dcf3ef4ee7e15f7ab0c7", size = 42870, upload-time = "2025-03-10T09:30:29.638Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/58/257350f7db99b4ae12b614a36256d9cc870d71d9e451e79c2dc3b23d7c3c/cssselect-1.3.0-py3-none-any.whl", hash = "sha256:56d1bf3e198080cc1667e137bc51de9cadfca259f03c2d4e09037b3e01e30f0d", size = 18786, upload-time = "2025-03-10T09:30:28.048Z" }, +] + +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, +] + +[[package]] +name = "django" +version = "4.2.27" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "sqlparse" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ce/ff/6aa5a94b85837af893ca82227301ac6ddf4798afda86151fb2066d26ca0a/django-4.2.27.tar.gz", hash = "sha256:b865fbe0f4a3d1ee36594c5efa42b20db3c8bbb10dff0736face1c6e4bda5b92", size = 10432781, upload-time = "2025-12-02T14:01:49.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dd/f5/1a2319cc090870bfe8c62ef5ad881a6b73b5f4ce7330c5cf2cb4f9536b12/django-4.2.27-py3-none-any.whl", hash = "sha256:f393a394053713e7d213984555c5b7d3caeee78b2ccb729888a0774dff6c11a8", size = 7995090, upload-time = "2025-12-02T14:01:44.234Z" }, +] + +[[package]] +name = "django-anymail" +version = "8.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/c0/30cb9cb0a597bbac68d3a7c7a4e078974e83b575c04a4c186729bb74b676/django-anymail-8.5.tar.gz", hash = "sha256:677e937dc9e2671ca7631abb1d94ddc6b840beb3d53c0fbf699e866a6a9ba92f", size = 80667, upload-time = "2022-01-19T23:12:37.287Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/4e/a784d0b72ddd54e3b4739ab0c5c8972989bded5086ba185f401bc68c51b4/django_anymail-8.5-py3-none-any.whl", hash = "sha256:2325932f56f914d96e0a54db850f2b246ed2277b753f75319620d051a51551e2", size = 100275, upload-time = "2022-01-19T23:12:35.729Z" }, +] + +[[package]] +name = "django-cache-memoize" +version = "0.1.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/39/35/2b3ea19a1a9e4ed1fbb9d87a4e34d536560d65185dc16749b190f7da7399/django-cache-memoize-0.1.10.tar.gz", hash = "sha256:63e8faa245a41c0dbad843807e9f21a6e59eba8e6e50df310fdf6485a6749843", size = 14600, upload-time = "2021-07-28T16:38:52.604Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/5e/bf8654e8591bfde379beed5243e3de5ad7c63dcd73df06a2d220a2278036/django_cache_memoize-0.1.10-py3-none-any.whl", hash = "sha256:676299313079cde9242ae84db0160e80b1d44e8dd6bc9b1f4f1247e11b30c9e0", size = 14416, upload-time = "2021-07-28T16:38:51.115Z" }, +] + +[[package]] +name = "django-countries" +version = "7.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/26/9bdf4384ee75e9056f3eabf9e8dbbbc7681612043dc1365a327b46e4edb8/django-countries-7.2.1.tar.gz", hash = "sha256:26878b54d36bedff30b4535ceefcb8af6784741a8b30b1b8a662fb14a936a4ab", size = 649955, upload-time = "2021-05-11T10:54:31.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/b3/e9148a3f8394b090dc961eb97ae549e22d8185645a6b3e8c31d5f6932d45/django_countries-7.2.1-py3-none-any.whl", hash = "sha256:adc965f1d348124274b7d918fc1aad5e29609758af999e1822baa9f2cc06d1b8", size = 825377, upload-time = "2021-05-11T10:54:27.155Z" }, +] + +[[package]] +name = "django-csp" +version = "3.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/76/bdb879b0e73798a8f5d568d19e77995c0319b82ddfa6c2fee4d15e956e1a/django_csp-3.7.tar.gz", hash = "sha256:01eda02ad3f10261c74131cdc0b5a6a62b7c7ad4fd017fbefb7a14776e0a9727", size = 12821, upload-time = "2020-08-12T18:50:35.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/04/1e3b703e584fef3522065415d9b2f7550d8996d7e590d9b70b8c480ecc69/django_csp-3.7-py2.py3-none-any.whl", hash = "sha256:01443a07723f9a479d498bd7bb63571aaa771e690f64bde515db6cdb76e8041a", size = 17390, upload-time = "2020-08-12T18:50:34.713Z" }, +] + +[[package]] +name = "django-extensions" +version = "3.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/aa/94ea07a87d52f484a562e701ee7af8dee4a43f3260b10d500d178ecbfcc7/django-extensions-3.2.1.tar.gz", hash = "sha256:2a4f4d757be2563cd1ff7cfdf2e57468f5f931cc88b23cf82ca75717aae504a4", size = 624971, upload-time = "2022-09-09T11:09:51.853Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/a8/36d25c69589a44680e49f8b1886f65379829af4464384bd10a205c93532a/django_extensions-3.2.1-py3-none-any.whl", hash = "sha256:421464be390289513f86cb5e18eb43e5dc1de8b4c27ba9faa3b91261b0d67e09", size = 229444, upload-time = "2022-09-09T11:09:47.085Z" }, +] + +[[package]] +name = "django-filter" +version = "21.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e3/90/819a74f0c9650a7ceda158d85a6010b4ce3d4e215e0c69ec9f3a733ce72f/django-filter-21.1.tar.gz", hash = "sha256:632a251fa8f1aadb4b8cceff932bb52fe2f826dd7dfe7f3eac40e5c463d6836e", size = 154188, upload-time = "2021-09-24T14:08:38.813Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/90/8fbf530e14dbcaf502cd80078cbae9e4f805f20888973488ebe8480c3c28/django_filter-21.1-py3-none-any.whl", hash = "sha256:f4a6737a30104c98d2e2a5fb93043f36dd7978e0c7ddc92f5998e85433ea5063", size = 81384, upload-time = "2021-09-24T14:08:37.152Z" }, +] + +[[package]] +name = "django-formtools" +version = "2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/b0/41ca0a8b7f2ce073f4cfca6adcc7b502a4a894fad9b80505b2ad13dc7aac/django-formtools-2.3.tar.gz", hash = "sha256:9663b6eca64777b68d6d4142efad8597fe9a685924673b25aa8a1dcff4db00c3", size = 83706, upload-time = "2021-04-19T03:58:47.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/dd/0bce8b9cc6dfa80a4c510e625f54be4348e799d9c594f98c1cd83e63cd2a/django_formtools-2.3-py3-none-any.whl", hash = "sha256:4699937e19ee041d803943714fe0c1c7ad4cab802600eb64bbf4cdd0a1bfe7d9", size = 148867, upload-time = "2021-04-19T03:58:32.131Z" }, +] + +[[package]] +name = "django-nose" +version = "1.4.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nose" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/d6/a340da9854cf0a2b54e23cf9147911b1e15a831911428983dd0158572ce9/django-nose-1.4.7.tar.gz", hash = "sha256:a4885cd002d65fd2de96e2bb2563ef477c3fbe207009360c015fca5c3b5561b7", size = 45041, upload-time = "2020-08-20T02:49:43.355Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/5e/804eda7b128162d215de14c0572717f16508cbdb899d4e839f51cef5481e/django_nose-1.4.7-py2.py3-none-any.whl", hash = "sha256:304adc447ee35b889b733d7106004f98aa401d8387ddcada5d4f2239d86790a9", size = 26470, upload-time = "2020-08-20T02:49:13.44Z" }, +] + +[[package]] +name = "django-otp" +version = "1.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b7/16/774bcfca894416f9f34867b75e60f7282830db140b109916061f77a9c611/django-otp-1.1.3.tar.gz", hash = "sha256:f002c71d4ea7f514590be00492980d3c87397b73dc20542e1c4fc00b66f2dda1", size = 61330, upload-time = "2021-11-30T18:11:31.727Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/a2/d0a4587be38d9c5a2981b45ba6386f5b05fa6309a5fe93f8917dc15b1b85/django_otp-1.1.3-py3-none-any.whl", hash = "sha256:8637be826c0465d0fd1710e4472efe9fc83883853a2141fefdbace9358d20003", size = 61438, upload-time = "2021-11-30T18:11:30.252Z" }, +] + +[[package]] +name = "django-phonenumber-field" +version = "7.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/fd/a00c79db4eab7bdcfcb419a14c4879a8f92e92951140c2d84a256c2cd835/django-phonenumber-field-7.3.0.tar.gz", hash = "sha256:f9cdb3de085f99c249328293a3b93d4e5fa440c0c8e3b99eb0d0f54748629797", size = 43005, upload-time = "2023-12-29T14:33:40.937Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/35/4f36dac859a1b9dbf9e737718d9b62e3502aca0eb74a10d659283b240992/django_phonenumber_field-7.3.0-py3-none-any.whl", hash = "sha256:bc6eaa49d1f9d870944f5280258db511e3a1ba5e2fbbed255488dceacae45d06", size = 66505, upload-time = "2023-12-29T14:33:36.859Z" }, +] + +[[package]] +name = "django-registration-redux" +version = "2.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/99/03/12bbb6262b26716c2df5b187bc321b6bd226d30b5ca60b080d641f079e9a/django-registration-redux-2.10.tar.gz", hash = "sha256:de25c3ae04ec466edc8a41e03d7ff817fdb996ffd00333550b9c4b960593fdff", size = 115983, upload-time = "2022-03-09T02:20:24.132Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/f4/6aae205d40dfe3fe57e9ba6b288def0c360bcb803b046c992ab494bdb8b4/django_registration_redux-2.10-py2.py3-none-any.whl", hash = "sha256:ef6817b300f56f82658058d6e060eef819ae882074721e8e98870ed195a24118", size = 213227, upload-time = "2022-03-09T02:20:21.883Z" }, +] + +[[package]] +name = "django-reversion" +version = "5.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5f/5c/9cb8596a9ade29bd849f0ac46b8287cfd9e031751dbcbfafc2294d475e8c/django-reversion-5.0.0.tar.gz", hash = "sha256:0bade3c399387451087f0c67835e0d3d186d767de6a5c5ba53a88eafc3f271c8", size = 71748, upload-time = "2022-02-20T16:49:44.05Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/0e/ad4a20275bd5ddcbd6fadcf64b5a6732471086dd611da1619c57e1b69391/django_reversion-5.0.0-py3-none-any.whl", hash = "sha256:7bea725de7f56769d89a5a712cf7b7f1b02abc27655432f2eb1a703264986d99", size = 86917, upload-time = "2022-02-20T16:49:42.198Z" }, +] + +[[package]] +name = "django-silk" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "autopep8" }, + { name = "django" }, + { name = "gprof2dot" }, + { name = "jinja2" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "requests" }, + { name = "sqlparse" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9a/93/3107a8d02a701ff9055b5027fd8d0ffa36194573cd9af130bc13d3af9c72/django-silk-4.4.0.tar.gz", hash = "sha256:476dac9f573bf206d34ef8a8407b51de28d4b7be8adbddcc3addcd25f2479e9b", size = 4358353, upload-time = "2022-06-20T16:13:31.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/ab/dcc5b9be7ab0b7981588e6eced9fd6749e22aab03bcf7ec649d0bad49dcd/django_silk-4.4.0-py3-none-any.whl", hash = "sha256:c3f673eef78cecc22c94a3683b0f870e6e8c7a7b79227e5568dca76b8c047278", size = 1802005, upload-time = "2022-06-20T16:14:06.751Z" }, +] + +[[package]] +name = "django-simple-history" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/d4/6fb7ff5410a7737bcb0be782b2af1958c13a9c5a0429a4f41a0a72d8214d/django-simple-history-3.0.0.tar.gz", hash = "sha256:66fe76c560054be393c52b1799661e104fbe372918d37d151e5d41c676158118", size = 533193, upload-time = "2021-04-19T15:02:28.15Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/5b/dbab8270380803077f6bc80941388dbb6c4d242628e0bae932943f686273/django_simple_history-3.0.0-py2.py3-none-any.whl", hash = "sha256:a312adfe8fbec4c450b08e641b11249a8a589a7e7d1ba2404764b8b5bed53552", size = 84847, upload-time = "2021-04-19T15:02:41.425Z" }, +] + +[[package]] +name = "django-storages" +version = "1.14.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ff/d6/2e50e378fff0408d558f36c4acffc090f9a641fd6e084af9e54d45307efa/django_storages-1.14.6.tar.gz", hash = "sha256:7a25ce8f4214f69ac9c7ce87e2603887f7ae99326c316bc8d2d75375e09341c9", size = 87587, upload-time = "2025-04-02T02:34:55.103Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/21/3cedee63417bc5553eed0c204be478071c9ab208e5e259e97287590194f1/django_storages-1.14.6-py3-none-any.whl", hash = "sha256:11b7b6200e1cb5ffcd9962bd3673a39c7d6a6109e8096f0e03d46fab3d3aabd9", size = 33095, upload-time = "2025-04-02T02:34:53.291Z" }, +] + +[[package]] +name = "django-stronghold" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/83/f38e0616ff658bbe62fb6e89b100ba9b19f3b351aa833dde37dcd296c8ca/django_stronghold-0.4.0-py2.py3-none-any.whl", hash = "sha256:4127d5f9c11f6582a1c03e7758256b1fe5c872f64f212980e5ad5c67f5eeaa3d", size = 9906, upload-time = "2020-01-17T16:34:53.25Z" }, +] + +[[package]] +name = "django-two-factor-auth" +version = "1.15.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "django-formtools" }, + { name = "django-otp" }, + { name = "django-phonenumber-field" }, + { name = "qrcode" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/64/dd90e403226707a54dd710ea87d28596e8a3f9c1310cd6ea038c4d12e9ff/django-two-factor-auth-1.15.5.tar.gz", hash = "sha256:87510ccdbf6053ba80aa217367fa122ff4cecd04c0afb8becbb2c96655057616", size = 158421, upload-time = "2023-09-22T07:19:32.985Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/f3/235ce3894bde12a99778f8278f236ea1638c1e2d32103491637ce2ded775/django_two_factor_auth-1.15.5-py3-none-any.whl", hash = "sha256:42fc95a250380a123faec301d350eab588c165af83d5c38840c1cc13f3aac746", size = 290755, upload-time = "2023-09-22T07:20:10.283Z" }, +] + +[[package]] +name = "django-user-agents" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "user-agents" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/37/f2/dd96cc880d7549cc9f67c8b1ad8e6695f9731658fdf8aa476f0bcb9c89c7/django-user_agents-0.4.0.tar.gz", hash = "sha256:cda8ae2146cee30e6867a07943f56ecc570b4391d725ab5309901a8b3e4a3514", size = 8501, upload-time = "2019-06-22T13:33:50.372Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/a3/31b2728702f13328cc65d6c8ed652ad8125a9a71489e445c11f188b39f79/django_user_agents-0.4.0-py3-none-any.whl", hash = "sha256:cd9d9f7158b23c5237b2dacb0bc4fffdf77fefe1d2633b5814d3874288ebdb5d", size = 8616, upload-time = "2019-06-22T13:33:48.259Z" }, +] + +[[package]] +name = "djangorestframework" +version = "3.15.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/ce/31482eb688bdb4e271027076199e1aa8d02507e530b6d272ab8b4481557c/djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad", size = 1067420, upload-time = "2024-06-19T07:59:32.891Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/b6/fa99d8f05eff3a9310286ae84c4059b08c301ae4ab33ae32e46e8ef76491/djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20", size = 1071235, upload-time = "2024-06-19T07:59:26.106Z" }, +] + +[[package]] +name = "docutils" +version = "0.22.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, +] + +[[package]] +name = "easyprocess" +version = "1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/e5/1071ad7de469bf3baae5b04d6c8019876c819c2d428cc1b0f15b4b31fc89/EasyProcess-1.1.tar.gz", hash = "sha256:885898302a57aab948973e8b5d32a4229392b9fb2d986ab1d4ffd590e5ba90ec", size = 11829, upload-time = "2022-01-15T10:58:56.146Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/cf/27d1f4b3bae5e566f94fc716e048120128cf603d5163638d22bcd0fc92d8/EasyProcess-1.1-py3-none-any.whl", hash = "sha256:82eed523a0a5eb12a81fa4eacd9f342caeb3f900eb4b798740e6696ad07e63f9", size = 8660, upload-time = "2022-01-15T10:58:54.473Z" }, +] + +[[package]] +name = "et-xmlfile" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/38/af70d7ab1ae9d4da450eeec1fa3918940a5fafb9055e934af8d6eb0c2313/et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54", size = 17234, upload-time = "2024-10-25T17:25:40.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "flatten-json" +version = "0.1.13" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/be/8f8e563004c7eae0b03be0fc6427a4ce07691c758250fdb31a9e934028d4/flatten_json-0.1.13.tar.gz", hash = "sha256:ee352333e8293e957ccb1b4597a111fc4f6da88ab74b8cb3f8f51eed1e12f500", size = 11676, upload-time = "2021-02-20T09:47:17.543Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/dd/174c3a6bbc66913d8d95f259026b93595e4944bde47dc3a60309acd0a36b/flatten_json-0.1.13-py3-none-any.whl", hash = "sha256:2998c8b7d2ba4b4073589ee1c460049bcb45cdf559ba1c738a38cd48a8e48d19", size = 7961, upload-time = "2023-10-27T17:16:41.774Z" }, +] + +[[package]] +name = "future" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490, upload-time = "2024-02-21T11:52:38.461Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326, upload-time = "2024-02-21T11:52:35.956Z" }, +] + +[[package]] +name = "gherkin-official" +version = "4.1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/f7/9e298a945b3982b9482c0a200d765772dcb4678e43c7257d2edfe1f6524e/gherkin-official-4.1.3.tar.gz", hash = "sha256:7f6fa7a3ceffda8bba0f56b42140cc6bae001d010fef336b5b2602252242395d", size = 24097, upload-time = "2017-05-04T09:38:55.375Z" } + +[[package]] +name = "gprof2dot" +version = "2025.4.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/fd/cad13fa1f7a463a607176432c4affa33ea162f02f58cc36de1d40d3e6b48/gprof2dot-2025.4.14.tar.gz", hash = "sha256:35743e2d2ca027bf48fa7cba37021aaf4a27beeae1ae8e05a50b55f1f921a6ce", size = 39536, upload-time = "2025-04-14T07:21:45.76Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/ed/89d760cb25279109b89eb52975a7b5479700d3114a2421ce735bfb2e7513/gprof2dot-2025.4.14-py3-none-any.whl", hash = "sha256:0742e4c0b4409a5e8777e739388a11e1ed3750be86895655312ea7c20bd0090e", size = 37555, upload-time = "2025-04-14T07:21:43.319Z" }, +] + +[[package]] +name = "gql-query-builder" +version = "0.1.dev17+ga983448b1" +source = { git = "https://github.com/eresearchqut/gql-query-builder?rev=a983448#a983448b116bfb42c1c23ca1007be9ee2adf6f8e" } + +[[package]] +name = "graphene" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "graphql-core" }, + { name = "graphql-relay" }, + { name = "python-dateutil" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/f6/bf62ff950c317ed03e77f3f6ddd7e34aaa98fe89d79ebd660c55343d8054/graphene-3.4.3.tar.gz", hash = "sha256:2a3786948ce75fe7e078443d37f609cbe5bb36ad8d6b828740ad3b95ed1a0aaa", size = 44739, upload-time = "2024-11-09T20:44:25.757Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/e0/61d8e98007182e6b2aca7cf65904721fb2e4bce0192272ab9cb6f69d8812/graphene-3.4.3-py2.py3-none-any.whl", hash = "sha256:820db6289754c181007a150db1f7fff544b94142b556d12e3ebc777a7bf36c71", size = 114894, upload-time = "2024-11-09T20:44:23.851Z" }, +] + +[[package]] +name = "graphene-django" +version = "3.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "graphene" }, + { name = "graphql-core" }, + { name = "graphql-relay" }, + { name = "promise" }, + { name = "text-unidecode" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/23/70/1b1d29d817eadc88cbbee2a049e5a1f6924f96cddbeec6c303660a3005b4/graphene-django-3.1.5.tar.gz", hash = "sha256:abe42f820b9731d94bebff6d73088d0dc2ffb8c8863a6d7bf3d378412d866a3b", size = 84744, upload-time = "2023-08-09T22:13:22.002Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/4e/5f3306f1664a4c3d77f21545914c866a66c419fdba1f43a62930a2ae57e7/graphene_django-3.1.5-py2.py3-none-any.whl", hash = "sha256:2e42742fae21fa50e514f3acae26a9bc6cb5e51c179a97b3db5390ff258ca816", size = 110165, upload-time = "2023-08-09T22:13:20.766Z" }, +] + +[[package]] +name = "graphql-core" +version = "3.2.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/9b/037a640a2983b09aed4a823f9cf1729e6d780b0671f854efa4727a7affbe/graphql_core-3.2.7.tar.gz", hash = "sha256:27b6904bdd3b43f2a0556dad5d579bdfdeab1f38e8e8788e555bdcb586a6f62c", size = 513484, upload-time = "2025-11-01T22:30:40.436Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/14/933037032608787fb92e365883ad6a741c235e0ff992865ec5d904a38f1e/graphql_core-3.2.7-py3-none-any.whl", hash = "sha256:17fc8f3ca4a42913d8e24d9ac9f08deddf0a0b2483076575757f6c412ead2ec0", size = 207262, upload-time = "2025-11-01T22:30:38.912Z" }, +] + +[[package]] +name = "graphql-relay" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "graphql-core" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/13/98fbf8d67552f102488ffc16c6f559ce71ea15f6294728d33928ab5ff14d/graphql-relay-3.2.0.tar.gz", hash = "sha256:1ff1c51298356e481a0be009ccdff249832ce53f30559c1338f22a0e0d17250c", size = 50027, upload-time = "2022-04-16T11:03:45.447Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/16/a4cf06adbc711bd364a73ce043b0b08d8fa5aae3df11b6ee4248bcdad2e0/graphql_relay-3.2.0-py3-none-any.whl", hash = "sha256:c9b22bd28b170ba1fe674c74384a8ff30a76c8e26f88ac3aa1584dd3179953e5", size = 16940, upload-time = "2022-04-16T11:03:43.895Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "humanize" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/66/a3921783d54be8a6870ac4ccffcd15c4dc0dd7fcce51c6d63b8c63935276/humanize-4.15.0.tar.gz", hash = "sha256:1dd098483eb1c7ee8e32eb2e99ad1910baefa4b75c3aff3a82f4d78688993b10", size = 83599, upload-time = "2025-12-20T20:16:13.19Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/7b/bca5613a0c3b542420cf92bd5e5fb8ebd5435ce1011a091f66bb7693285e/humanize-4.15.0-py3-none-any.whl", hash = "sha256:b1186eb9f5a9749cd9cb8565aee77919dd7c8d076161cf44d70e59e3301e1769", size = 132203, upload-time = "2025-12-20T20:16:11.67Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "ipython" +version = "9.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/12/51/a703c030f4928646d390b4971af4938a1b10c9dfce694f0d99a0bb073cb2/ipython-9.8.0.tar.gz", hash = "sha256:8e4ce129a627eb9dd221c41b1d2cdaed4ef7c9da8c17c63f6f578fe231141f83", size = 4424940, upload-time = "2025-12-03T10:18:24.353Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl", hash = "sha256:ebe6d1d58d7d988fbf23ff8ff6d8e1622cfdb194daf4b7b73b792c4ec3b85385", size = 621374, upload-time = "2025-12-03T10:18:22.335Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jmespath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843, upload-time = "2022-06-17T18:00:12.224Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256, upload-time = "2022-06-17T18:00:10.251Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "pyrsistent" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/67/36cfd516f7b3560bbf7183d7a0f82bb9514d2a5f4e1d682a8a1d55d8031d/jsonschema-4.4.0.tar.gz", hash = "sha256:636694eb41b3535ed608fe04129f26542b59ed99808b4f688aa32dcf55317a83", size = 313519, upload-time = "2022-01-12T12:22:03.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/b2/2c4af6a97c3f12c6d5a72b41d328c3996e14e1e46701df3fac1ed65119c9/jsonschema-4.4.0-py3-none-any.whl", hash = "sha256:77281a1f71684953ee8b3d488371b162419767973789272434bbc3f29d9c8823", size = 72687, upload-time = "2022-01-12T12:22:02.485Z" }, +] + +[[package]] +name = "langcodes" +version = "3.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/ec/9955d772ecac0bdfb5d706d64f185ac68bd0d4092acdc2c5a1882c824369/langcodes-3.3.0.tar.gz", hash = "sha256:794d07d5a28781231ac335a1561b8442f8648ca07cd518310aeb45d6f0807ef6", size = 189505, upload-time = "2021-11-11T21:35:38.412Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/c3/0d04d248624a181e57c2870127dfa8d371973561caf54333c85e8f9133a2/langcodes-3.3.0-py3-none-any.whl", hash = "sha256:4d89fc9acb6e9c8fdef70bcdf376113a3db09b67285d9e1d534de6d8818e7e69", size = 181648, upload-time = "2021-11-11T21:35:37.048Z" }, +] + +[[package]] +name = "language-data" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "marisa-trie" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/ce/3f144716a9f2cbf42aa86ebc8b085a184be25c80aa453eea17c294d239c1/language_data-1.3.0.tar.gz", hash = "sha256:7600ef8aa39555145d06c89f0c324bf7dab834ea0b0a439d8243762e3ebad7ec", size = 5129310, upload-time = "2024-11-19T10:21:37.912Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/e9/5a5ffd9b286db82be70d677d0a91e4d58f7912bb8dd026ddeeb4abe70679/language_data-1.3.0-py3-none-any.whl", hash = "sha256:e2ee943551b5ae5f89cd0e801d1fc3835bb0ef5b7e9c3a4e8e17b2b214548fbf", size = 5385760, upload-time = "2024-11-19T10:21:36.005Z" }, +] + +[[package]] +name = "lark" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/fc/9c06cb2a56d3fbc1b9b65a78744694c3c74891e1760c716f1dd8d9a5a3d7/lark-1.0.0.tar.gz", hash = "sha256:2269dee215e6c689d5ce9d34fdc6e749d0c1c763add3fc7935938ebd7da159cb", size = 238730, upload-time = "2021-11-15T08:16:30.103Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/cc/eccab4b77acf60a16658e010d072ecf31fd6bf9260335689e5eeef6d9552/lark-1.0.0-py2.py3-none-any.whl", hash = "sha256:10818563b44e18ea264b5013a80fe04406999ad51bacc74214f69f13d95af6e1", size = 109133, upload-time = "2021-11-15T08:16:32.538Z" }, +] + +[[package]] +name = "levenshtein" +version = "0.27.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "rapidfuzz" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/82/56/dcf68853b062e3b94bdc3d011cc4198779abc5b9dc134146a062920ce2e2/levenshtein-0.27.3.tar.gz", hash = "sha256:1ac326b2c84215795163d8a5af471188918b8797b4953ec87aaba22c9c1f9fc0", size = 393269, upload-time = "2025-11-01T12:14:31.04Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/f2/162e9ea7490b36bbf05776c8e3a8114c75aa78546ddda8e8f36731db3da6/levenshtein-0.27.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e55aa9f9453fd89d4a9ff1f3c4a650b307d5f61a7eed0568a52fbd2ff2eba107", size = 169230, upload-time = "2025-11-01T12:13:23.735Z" }, + { url = "https://files.pythonhosted.org/packages/01/2d/7316ba7f94e3d60e89bd120526bc71e4812866bb7162767a2a10f73f72c5/levenshtein-0.27.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae4d484453c48939ecd01c5c213530c68dd5cd6e5090f0091ef69799ec7a8a9f", size = 158643, upload-time = "2025-11-01T12:13:25.549Z" }, + { url = "https://files.pythonhosted.org/packages/5e/87/85433cb1e51c45016f061d96fea3106b6969f700e2cbb56c15de82d0deeb/levenshtein-0.27.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d18659832567ee387b266be390da0de356a3aa6cf0e8bc009b6042d8188e131f", size = 132881, upload-time = "2025-11-01T12:13:26.822Z" }, + { url = "https://files.pythonhosted.org/packages/40/1c/3ce66c9a7da169a43dd89146d69df9dec935e6f86c70c6404f48d1291d2c/levenshtein-0.27.3-cp313-cp313-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027b3d142cc8ea2ab4e60444d7175f65a94dde22a54382b2f7b47cc24936eb53", size = 114650, upload-time = "2025-11-01T12:13:28.382Z" }, + { url = "https://files.pythonhosted.org/packages/73/60/7138e98884ca105c76ef192f5b43165d6eac6f32b432853ebe9f09ee50c9/levenshtein-0.27.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffdca6989368cc64f347f0423c528520f12775b812e170a0eb0c10e4c9b0f3ff", size = 153127, upload-time = "2025-11-01T12:13:29.781Z" }, + { url = "https://files.pythonhosted.org/packages/df/8f/664ac8b83026d7d1382866b68babae17e92b7b6ff8dc3c6205c0066b8ce1/levenshtein-0.27.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fa00ab389386032b02a1c9050ec3c6aa824d2bbcc692548fdc44a46b71c058c6", size = 1114602, upload-time = "2025-11-01T12:13:31.651Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c8/8905d96cf2d7ed6af7eb39a8be0925ef335729473c1e9d1f56230ecaffc5/levenshtein-0.27.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:691c9003c6c481b899a5c2f72e8ce05a6d956a9668dc75f2a3ce9f4381a76dc6", size = 1008036, upload-time = "2025-11-01T12:13:33.006Z" }, + { url = "https://files.pythonhosted.org/packages/c7/57/01c37608121380a6357a297625562adad1c1fc8058d4f62279b735108927/levenshtein-0.27.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:12f7fc8bf0c24492fe97905348e020b55b9fc6dbaab7cd452566d1a466cb5e15", size = 1185338, upload-time = "2025-11-01T12:13:34.452Z" }, + { url = "https://files.pythonhosted.org/packages/dd/57/bceab41d40b58dee7927a8d1d18ed3bff7c95c5e530fb60093ce741a8c26/levenshtein-0.27.3-cp313-cp313-win32.whl", hash = "sha256:9f4872e4e19ee48eed39f214eea4eca42e5ef303f8a4a488d8312370674dbf3a", size = 84562, upload-time = "2025-11-01T12:13:35.858Z" }, + { url = "https://files.pythonhosted.org/packages/42/1d/74f1ff589bb687d0cad2bbdceef208dc070f56d1e38a3831da8c00bf13bb/levenshtein-0.27.3-cp313-cp313-win_amd64.whl", hash = "sha256:83aa2422e9a9af2c9d3e56a53e3e8de6bae58d1793628cae48c4282577c5c2c6", size = 94658, upload-time = "2025-11-01T12:13:36.963Z" }, + { url = "https://files.pythonhosted.org/packages/21/3c/22c86d3c8f254141096fd6089d2e9fdf98b1472c7a5d79d36d3557ec2d83/levenshtein-0.27.3-cp313-cp313-win_arm64.whl", hash = "sha256:d4adaf1edbcf38c3f2e290b52f4dcb5c6deff20308c26ef1127a106bc2d23e9f", size = 86929, upload-time = "2025-11-01T12:13:37.997Z" }, + { url = "https://files.pythonhosted.org/packages/0e/bc/9b7cf1b5fa098b86844d42de22549304699deff309c5c9e28b9a3fc4076a/levenshtein-0.27.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:272e24764b8210337b65a1cfd69ce40df5d2de1a3baf1234e7f06d2826ba2e7a", size = 170360, upload-time = "2025-11-01T12:13:39.019Z" }, + { url = "https://files.pythonhosted.org/packages/dc/95/997f2c83bd4712426bf0de8143b5e4403c7ebbafb5d1271983e774de3ae7/levenshtein-0.27.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:329a8e748a4e14d56daaa11f07bce3fde53385d05bad6b3f6dd9ee7802cdc915", size = 159098, upload-time = "2025-11-01T12:13:40.17Z" }, + { url = "https://files.pythonhosted.org/packages/fc/96/123c3316ae2f72c73be4fba9756924af015da4c0e5b12804f5753c0ee511/levenshtein-0.27.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5fea1a9c6b9cc8729e467e2174b4359ff6bac27356bb5f31898e596b4ce133a", size = 136655, upload-time = "2025-11-01T12:13:41.262Z" }, + { url = "https://files.pythonhosted.org/packages/45/72/a3180d437736b1b9eacc3100be655a756deafb91de47c762d40eb45a9d91/levenshtein-0.27.3-cp313-cp313t-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3a61aa825819b6356555091d8a575d1235bd9c3753a68316a261af4856c3b487", size = 117511, upload-time = "2025-11-01T12:13:42.647Z" }, + { url = "https://files.pythonhosted.org/packages/61/f9/ba7c546a4b99347938e6661104064ab6a3651c601d59f241ffdc37510ecc/levenshtein-0.27.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a51de7a514e8183f0a82f2947d01b014d2391426543b1c076bf5a26328cec4e4", size = 155656, upload-time = "2025-11-01T12:13:44.208Z" }, + { url = "https://files.pythonhosted.org/packages/42/cd/5edd6e1e02c3e47c8121761756dd0f85f816b636f25509118b687e6b0f96/levenshtein-0.27.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53cbf726d6e92040c9be7e594d959d496bd62597ea48eba9d96105898acbeafe", size = 1116689, upload-time = "2025-11-01T12:13:45.485Z" }, + { url = "https://files.pythonhosted.org/packages/95/67/25ca0119e0c6ec17226c72638f48ef8887124597ac48ad5da111c0b3a825/levenshtein-0.27.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:191b358afead8561c4fcfed22f83c13bb6c8da5f5789e277f0c5aa1c45ca612f", size = 1003166, upload-time = "2025-11-01T12:13:47.126Z" }, + { url = "https://files.pythonhosted.org/packages/45/64/ab216f3fb3cef1ee7e222665537f9340d828ef84c99409ba31f2ef2a3947/levenshtein-0.27.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ba1318d0635b834b8f0397014a7c43f007e65fce396a47614780c881bdff828b", size = 1189362, upload-time = "2025-11-01T12:13:48.627Z" }, + { url = "https://files.pythonhosted.org/packages/31/58/b150034858de0899a5a222974b6710618ebc0779a0695df070f7ab559a0b/levenshtein-0.27.3-cp313-cp313t-win32.whl", hash = "sha256:8dd9e1db6c3b35567043e155a686e4827c4aa28a594bd81e3eea84d3a1bd5875", size = 86149, upload-time = "2025-11-01T12:13:50.588Z" }, + { url = "https://files.pythonhosted.org/packages/0a/c4/bbe46a11073641450200e6a604b3b62d311166e8061c492612a40e560e85/levenshtein-0.27.3-cp313-cp313t-win_amd64.whl", hash = "sha256:7813ecdac7a6223264ebfea0c8d69959c43d21a99694ef28018d22c4265c2af6", size = 96685, upload-time = "2025-11-01T12:13:51.641Z" }, + { url = "https://files.pythonhosted.org/packages/23/65/30b362ad9bfc1085741776a08b6ddee3f434e9daac2920daaee2e26271bf/levenshtein-0.27.3-cp313-cp313t-win_arm64.whl", hash = "sha256:8f05a0d23d13a6f802c7af595d0e43f5b9b98b6ed390cec7a35cb5d6693b882b", size = 88538, upload-time = "2025-11-01T12:13:52.757Z" }, + { url = "https://files.pythonhosted.org/packages/f3/e1/2f705da403f865a5fa3449b155738dc9c53021698fd6926253a9af03180b/levenshtein-0.27.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a6728bfae9a86002f0223576675fc7e2a6e7735da47185a1d13d1eaaa73dd4be", size = 169457, upload-time = "2025-11-01T12:13:53.778Z" }, + { url = "https://files.pythonhosted.org/packages/76/2c/bb6ef359e007fe7b6b3195b68a94f4dd3ecd1885ee337ee8fbd4df55996f/levenshtein-0.27.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8e5037c4a6f97a238e24aad6f98a1e984348b7931b1b04b6bd02bd4f8238150d", size = 158680, upload-time = "2025-11-01T12:13:55.005Z" }, + { url = "https://files.pythonhosted.org/packages/51/7b/de1999f4cf1cfebc3fbbf03a6d58498952d6560d9798af4b0a566e6b6f30/levenshtein-0.27.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6cf5ecf9026bf24cf66ad019c6583f50058fae3e1b3c20e8812455b55d597f1", size = 133167, upload-time = "2025-11-01T12:13:56.426Z" }, + { url = "https://files.pythonhosted.org/packages/c7/da/aaa7f3a0a8ae8744b284043653652db3d7d93595517f9ed8158c03287692/levenshtein-0.27.3-cp314-cp314-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9285084bd2fc19adb47dab54ed4a71f57f78fe0d754e4a01e3c75409a25aed24", size = 114530, upload-time = "2025-11-01T12:13:57.883Z" }, + { url = "https://files.pythonhosted.org/packages/29/ce/ed422816fb30ffa3bc11597b30d5deca06b4a1388707a04215da73c65b53/levenshtein-0.27.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce3bbbe92172a08b599d79956182c6b7ab6ec8d4adbe7237417a363b968ad87b", size = 153325, upload-time = "2025-11-01T12:13:59.318Z" }, + { url = "https://files.pythonhosted.org/packages/d9/5a/a225477a0bda154f19f1c07a5e35500d631ae25dfd620b479027d79f0d4c/levenshtein-0.27.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9dac48fab9d166ca90e12fb6cf6c7c8eb9c41aacf7136584411e20f7f136f745", size = 1114956, upload-time = "2025-11-01T12:14:00.543Z" }, + { url = "https://files.pythonhosted.org/packages/ca/c4/a1be1040f3cce516a5e2be68453fd0c32ac63b2e9d31f476723fd8002c09/levenshtein-0.27.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d37a83722dc5326c93d17078e926c4732dc4f3488dc017c6839e34cd16af92b7", size = 1007610, upload-time = "2025-11-01T12:14:02.036Z" }, + { url = "https://files.pythonhosted.org/packages/86/d7/6f50e8a307e0c2befd819b481eb3a4c2eacab3dd8101982423003fac8ea3/levenshtein-0.27.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3466cb8294ce586e49dd467560a153ab8d296015c538223f149f9aefd3d9f955", size = 1185379, upload-time = "2025-11-01T12:14:03.385Z" }, + { url = "https://files.pythonhosted.org/packages/6b/e5/5d8fb1b3ebd5735f53221bf95c923066bcfc132234925820128f7eee5b47/levenshtein-0.27.3-cp314-cp314-win32.whl", hash = "sha256:c848bf2457b268672b7e9e73b44f18f49856420ac50b2564cf115a6e4ef82688", size = 86328, upload-time = "2025-11-01T12:14:04.74Z" }, + { url = "https://files.pythonhosted.org/packages/30/82/8a9ccbdb4e38bd4d516f2804999dccb8cb4bcb4e33f52851735da0c73ea7/levenshtein-0.27.3-cp314-cp314-win_amd64.whl", hash = "sha256:742633f024362a4ed6ef9d7e75d68f74b041ae738985fcf55a0e6d1d4cade438", size = 96640, upload-time = "2025-11-01T12:14:06.24Z" }, + { url = "https://files.pythonhosted.org/packages/14/86/f9d15919f59f5d92c6baa500315e1fa0143a39d811427b83c54f038267ca/levenshtein-0.27.3-cp314-cp314-win_arm64.whl", hash = "sha256:9eed6851224b19e8d588ddb8eb8a4ae3c2dcabf3d1213985f0b94a67e517b1df", size = 89689, upload-time = "2025-11-01T12:14:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f6/10f44975ae6dc3047b2cd260e3d4c3a5258b8d10690a42904115de24fc51/levenshtein-0.27.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:77de69a345c76227b51a4521cd85442eb3da54c7eb6a06663a20c058fc49e683", size = 170518, upload-time = "2025-11-01T12:14:09.196Z" }, + { url = "https://files.pythonhosted.org/packages/08/07/fa294a145a0c99a814a9a807614962c1ee0f5749ca691645980462027d5d/levenshtein-0.27.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:eba2756dc1f5b962b0ff80e49abb2153d5e809cc5e7fa5e85be9410ce474795d", size = 159097, upload-time = "2025-11-01T12:14:10.404Z" }, + { url = "https://files.pythonhosted.org/packages/ae/50/24bdf37813fc30f293e53b46022b091144f4737a6a66663d2235b311bb98/levenshtein-0.27.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c8fcb498287e971d84260f67808ff1a06b3f6212d80fea75cf5155db80606ff", size = 136650, upload-time = "2025-11-01T12:14:11.579Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a9/0399c7a190b277cdea3acc801129d9d30da57c3fa79519e7b8c3f080d86c/levenshtein-0.27.3-cp314-cp314t-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f067092c67464faab13e00a5c1a80da93baca8955d4d49579861400762e35591", size = 117515, upload-time = "2025-11-01T12:14:12.877Z" }, + { url = "https://files.pythonhosted.org/packages/bf/a4/1c27533e97578b385a4b8079abe8d1ce2e514717c761efbe4bf7bbd0ac2e/levenshtein-0.27.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92415f32c68491203f2855d05eef3277d376182d014cf0859c013c89f277fbbf", size = 155711, upload-time = "2025-11-01T12:14:13.985Z" }, + { url = "https://files.pythonhosted.org/packages/50/35/bbc26638394a72b1e31a685ec251c995ee66a630c7e5c86f98770928b632/levenshtein-0.27.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ef61eeaf1e0a42d7d947978d981fe4b9426b98b3dd8c1582c535f10dee044c3f", size = 1116692, upload-time = "2025-11-01T12:14:15.359Z" }, + { url = "https://files.pythonhosted.org/packages/cd/83/32fcf28b388f8dc6c36b54552b9bae289dab07d43df104893158c834cbcc/levenshtein-0.27.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:103bb2e9049d1aa0d1216dd09c1c9106ecfe7541bbdc1a0490b9357d42eec8f2", size = 1003167, upload-time = "2025-11-01T12:14:17.469Z" }, + { url = "https://files.pythonhosted.org/packages/d1/79/1fbf2877ec4b819f373a32ebe3c48a61ee810693593a6015108b0be97b78/levenshtein-0.27.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6a64ddd1986b2a4c468b09544382287315c53585eb067f6e200c337741e057ee", size = 1189417, upload-time = "2025-11-01T12:14:19.081Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ac/dad4e09f1f7459c64172e48e40ed2baf3aa92d38205bcbd1b4ff00853701/levenshtein-0.27.3-cp314-cp314t-win32.whl", hash = "sha256:957244f27dc284ccb030a8b77b8a00deb7eefdcd70052a4b1d96f375780ae9dc", size = 88144, upload-time = "2025-11-01T12:14:20.667Z" }, + { url = "https://files.pythonhosted.org/packages/c0/61/cd51dc8b8a382e17c559a9812734c3a9afc2dab7d36253516335ee16ae50/levenshtein-0.27.3-cp314-cp314t-win_amd64.whl", hash = "sha256:ccd7eaa6d8048c3ec07c93cfbcdefd4a3ae8c6aca3a370f2023ee69341e5f076", size = 98516, upload-time = "2025-11-01T12:14:21.786Z" }, + { url = "https://files.pythonhosted.org/packages/27/5e/3fb67e882c1fee01ebb7abc1c0a6669e5ff8acd060e93bfe7229e9ce6e4f/levenshtein-0.27.3-cp314-cp314t-win_arm64.whl", hash = "sha256:1d8520b89b7a27bb5aadbcc156715619bcbf556a8ac46ad932470945dca6e1bd", size = 91020, upload-time = "2025-11-01T12:14:22.944Z" }, +] + +[[package]] +name = "lxml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/88/262177de60548e5a2bfc46ad28232c9e9cbde697bd94132aeb80364675cb/lxml-6.0.2.tar.gz", hash = "sha256:cd79f3367bd74b317dda655dc8fcfa304d9eb6e4fb06b7168c5cf27f96e0cd62", size = 4073426, upload-time = "2025-09-22T04:04:59.287Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/fd/4e8f0540608977aea078bf6d79f128e0e2c2bba8af1acf775c30baa70460/lxml-6.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9b33d21594afab46f37ae58dfadd06636f154923c4e8a4d754b0127554eb2e77", size = 8648494, upload-time = "2025-09-22T04:01:54.242Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f4/2a94a3d3dfd6c6b433501b8d470a1960a20ecce93245cf2db1706adf6c19/lxml-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c8963287d7a4c5c9a432ff487c52e9c5618667179c18a204bdedb27310f022f", size = 4661146, upload-time = "2025-09-22T04:01:56.282Z" }, + { url = "https://files.pythonhosted.org/packages/25/2e/4efa677fa6b322013035d38016f6ae859d06cac67437ca7dc708a6af7028/lxml-6.0.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1941354d92699fb5ffe6ed7b32f9649e43c2feb4b97205f75866f7d21aa91452", size = 4946932, upload-time = "2025-09-22T04:01:58.989Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0f/526e78a6d38d109fdbaa5049c62e1d32fdd70c75fb61c4eadf3045d3d124/lxml-6.0.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb2f6ca0ae2d983ded09357b84af659c954722bbf04dea98030064996d156048", size = 5100060, upload-time = "2025-09-22T04:02:00.812Z" }, + { url = "https://files.pythonhosted.org/packages/81/76/99de58d81fa702cc0ea7edae4f4640416c2062813a00ff24bd70ac1d9c9b/lxml-6.0.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb2a12d704f180a902d7fa778c6d71f36ceb7b0d317f34cdc76a5d05aa1dd1df", size = 5019000, upload-time = "2025-09-22T04:02:02.671Z" }, + { url = "https://files.pythonhosted.org/packages/b5/35/9e57d25482bc9a9882cb0037fdb9cc18f4b79d85df94fa9d2a89562f1d25/lxml-6.0.2-cp313-cp313-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:6ec0e3f745021bfed19c456647f0298d60a24c9ff86d9d051f52b509663feeb1", size = 5348496, upload-time = "2025-09-22T04:02:04.904Z" }, + { url = "https://files.pythonhosted.org/packages/a6/8e/cb99bd0b83ccc3e8f0f528e9aa1f7a9965dfec08c617070c5db8d63a87ce/lxml-6.0.2-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:846ae9a12d54e368933b9759052d6206a9e8b250291109c48e350c1f1f49d916", size = 5643779, upload-time = "2025-09-22T04:02:06.689Z" }, + { url = "https://files.pythonhosted.org/packages/d0/34/9e591954939276bb679b73773836c6684c22e56d05980e31d52a9a8deb18/lxml-6.0.2-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef9266d2aa545d7374938fb5c484531ef5a2ec7f2d573e62f8ce722c735685fd", size = 5244072, upload-time = "2025-09-22T04:02:08.587Z" }, + { url = "https://files.pythonhosted.org/packages/8d/27/b29ff065f9aaca443ee377aff699714fcbffb371b4fce5ac4ca759e436d5/lxml-6.0.2-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:4077b7c79f31755df33b795dc12119cb557a0106bfdab0d2c2d97bd3cf3dffa6", size = 4718675, upload-time = "2025-09-22T04:02:10.783Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/f756f9c2cd27caa1a6ef8c32ae47aadea697f5c2c6d07b0dae133c244fbe/lxml-6.0.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a7c5d5e5f1081955358533be077166ee97ed2571d6a66bdba6ec2f609a715d1a", size = 5255171, upload-time = "2025-09-22T04:02:12.631Z" }, + { url = "https://files.pythonhosted.org/packages/61/46/bb85ea42d2cb1bd8395484fd72f38e3389611aa496ac7772da9205bbda0e/lxml-6.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8f8d0cbd0674ee89863a523e6994ac25fd5be9c8486acfc3e5ccea679bad2679", size = 5057175, upload-time = "2025-09-22T04:02:14.718Z" }, + { url = "https://files.pythonhosted.org/packages/95/0c/443fc476dcc8e41577f0af70458c50fe299a97bb6b7505bb1ae09aa7f9ac/lxml-6.0.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2cbcbf6d6e924c28f04a43f3b6f6e272312a090f269eff68a2982e13e5d57659", size = 4785688, upload-time = "2025-09-22T04:02:16.957Z" }, + { url = "https://files.pythonhosted.org/packages/48/78/6ef0b359d45bb9697bc5a626e1992fa5d27aa3f8004b137b2314793b50a0/lxml-6.0.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dfb874cfa53340009af6bdd7e54ebc0d21012a60a4e65d927c2e477112e63484", size = 5660655, upload-time = "2025-09-22T04:02:18.815Z" }, + { url = "https://files.pythonhosted.org/packages/ff/ea/e1d33808f386bc1339d08c0dcada6e4712d4ed8e93fcad5f057070b7988a/lxml-6.0.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb8dae0b6b8b7f9e96c26fdd8121522ce5de9bb5538010870bd538683d30e9a2", size = 5247695, upload-time = "2025-09-22T04:02:20.593Z" }, + { url = "https://files.pythonhosted.org/packages/4f/47/eba75dfd8183673725255247a603b4ad606f4ae657b60c6c145b381697da/lxml-6.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:358d9adae670b63e95bc59747c72f4dc97c9ec58881d4627fe0120da0f90d314", size = 5269841, upload-time = "2025-09-22T04:02:22.489Z" }, + { url = "https://files.pythonhosted.org/packages/76/04/5c5e2b8577bc936e219becb2e98cdb1aca14a4921a12995b9d0c523502ae/lxml-6.0.2-cp313-cp313-win32.whl", hash = "sha256:e8cd2415f372e7e5a789d743d133ae474290a90b9023197fd78f32e2dc6873e2", size = 3610700, upload-time = "2025-09-22T04:02:24.465Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0a/4643ccc6bb8b143e9f9640aa54e38255f9d3b45feb2cbe7ae2ca47e8782e/lxml-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:b30d46379644fbfc3ab81f8f82ae4de55179414651f110a1514f0b1f8f6cb2d7", size = 4010347, upload-time = "2025-09-22T04:02:26.286Z" }, + { url = "https://files.pythonhosted.org/packages/31/ef/dcf1d29c3f530577f61e5fe2f1bd72929acf779953668a8a47a479ae6f26/lxml-6.0.2-cp313-cp313-win_arm64.whl", hash = "sha256:13dcecc9946dca97b11b7c40d29fba63b55ab4170d3c0cf8c0c164343b9bfdcf", size = 3671248, upload-time = "2025-09-22T04:02:27.918Z" }, + { url = "https://files.pythonhosted.org/packages/03/15/d4a377b385ab693ce97b472fe0c77c2b16ec79590e688b3ccc71fba19884/lxml-6.0.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:b0c732aa23de8f8aec23f4b580d1e52905ef468afb4abeafd3fec77042abb6fe", size = 8659801, upload-time = "2025-09-22T04:02:30.113Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e8/c128e37589463668794d503afaeb003987373c5f94d667124ffd8078bbd9/lxml-6.0.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4468e3b83e10e0317a89a33d28f7aeba1caa4d1a6fd457d115dd4ffe90c5931d", size = 4659403, upload-time = "2025-09-22T04:02:32.119Z" }, + { url = "https://files.pythonhosted.org/packages/00/ce/74903904339decdf7da7847bb5741fc98a5451b42fc419a86c0c13d26fe2/lxml-6.0.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:abd44571493973bad4598a3be7e1d807ed45aa2adaf7ab92ab7c62609569b17d", size = 4966974, upload-time = "2025-09-22T04:02:34.155Z" }, + { url = "https://files.pythonhosted.org/packages/1f/d3/131dec79ce61c5567fecf82515bd9bc36395df42501b50f7f7f3bd065df0/lxml-6.0.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:370cd78d5855cfbffd57c422851f7d3864e6ae72d0da615fca4dad8c45d375a5", size = 5102953, upload-time = "2025-09-22T04:02:36.054Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ea/a43ba9bb750d4ffdd885f2cd333572f5bb900cd2408b67fdda07e85978a0/lxml-6.0.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:901e3b4219fa04ef766885fb40fa516a71662a4c61b80c94d25336b4934b71c0", size = 5055054, upload-time = "2025-09-22T04:02:38.154Z" }, + { url = "https://files.pythonhosted.org/packages/60/23/6885b451636ae286c34628f70a7ed1fcc759f8d9ad382d132e1c8d3d9bfd/lxml-6.0.2-cp314-cp314-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:a4bf42d2e4cf52c28cc1812d62426b9503cdb0c87a6de81442626aa7d69707ba", size = 5352421, upload-time = "2025-09-22T04:02:40.413Z" }, + { url = "https://files.pythonhosted.org/packages/48/5b/fc2ddfc94ddbe3eebb8e9af6e3fd65e2feba4967f6a4e9683875c394c2d8/lxml-6.0.2-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2c7fdaa4d7c3d886a42534adec7cfac73860b89b4e5298752f60aa5984641a0", size = 5673684, upload-time = "2025-09-22T04:02:42.288Z" }, + { url = "https://files.pythonhosted.org/packages/29/9c/47293c58cc91769130fbf85531280e8cc7868f7fbb6d92f4670071b9cb3e/lxml-6.0.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98a5e1660dc7de2200b00d53fa00bcd3c35a3608c305d45a7bbcaf29fa16e83d", size = 5252463, upload-time = "2025-09-22T04:02:44.165Z" }, + { url = "https://files.pythonhosted.org/packages/9b/da/ba6eceb830c762b48e711ded880d7e3e89fc6c7323e587c36540b6b23c6b/lxml-6.0.2-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:dc051506c30b609238d79eda75ee9cab3e520570ec8219844a72a46020901e37", size = 4698437, upload-time = "2025-09-22T04:02:46.524Z" }, + { url = "https://files.pythonhosted.org/packages/a5/24/7be3f82cb7990b89118d944b619e53c656c97dc89c28cfb143fdb7cd6f4d/lxml-6.0.2-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8799481bbdd212470d17513a54d568f44416db01250f49449647b5ab5b5dccb9", size = 5269890, upload-time = "2025-09-22T04:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/1b/bd/dcfb9ea1e16c665efd7538fc5d5c34071276ce9220e234217682e7d2c4a5/lxml-6.0.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9261bb77c2dab42f3ecd9103951aeca2c40277701eb7e912c545c1b16e0e4917", size = 5097185, upload-time = "2025-09-22T04:02:50.746Z" }, + { url = "https://files.pythonhosted.org/packages/21/04/a60b0ff9314736316f28316b694bccbbabe100f8483ad83852d77fc7468e/lxml-6.0.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:65ac4a01aba353cfa6d5725b95d7aed6356ddc0a3cd734de00124d285b04b64f", size = 4745895, upload-time = "2025-09-22T04:02:52.968Z" }, + { url = "https://files.pythonhosted.org/packages/d6/bd/7d54bd1846e5a310d9c715921c5faa71cf5c0853372adf78aee70c8d7aa2/lxml-6.0.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b22a07cbb82fea98f8a2fd814f3d1811ff9ed76d0fc6abc84eb21527596e7cc8", size = 5695246, upload-time = "2025-09-22T04:02:54.798Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/5643d6ab947bc371da21323acb2a6e603cedbe71cb4c99c8254289ab6f4e/lxml-6.0.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d759cdd7f3e055d6bc8d9bec3ad905227b2e4c785dc16c372eb5b5e83123f48a", size = 5260797, upload-time = "2025-09-22T04:02:57.058Z" }, + { url = "https://files.pythonhosted.org/packages/33/da/34c1ec4cff1eea7d0b4cd44af8411806ed943141804ac9c5d565302afb78/lxml-6.0.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:945da35a48d193d27c188037a05fec5492937f66fb1958c24fc761fb9d40d43c", size = 5277404, upload-time = "2025-09-22T04:02:58.966Z" }, + { url = "https://files.pythonhosted.org/packages/82/57/4eca3e31e54dc89e2c3507e1cd411074a17565fa5ffc437c4ae0a00d439e/lxml-6.0.2-cp314-cp314-win32.whl", hash = "sha256:be3aaa60da67e6153eb15715cc2e19091af5dc75faef8b8a585aea372507384b", size = 3670072, upload-time = "2025-09-22T04:03:38.05Z" }, + { url = "https://files.pythonhosted.org/packages/e3/e0/c96cf13eccd20c9421ba910304dae0f619724dcf1702864fd59dd386404d/lxml-6.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:fa25afbadead523f7001caf0c2382afd272c315a033a7b06336da2637d92d6ed", size = 4080617, upload-time = "2025-09-22T04:03:39.835Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5d/b3f03e22b3d38d6f188ef044900a9b29b2fe0aebb94625ce9fe244011d34/lxml-6.0.2-cp314-cp314-win_arm64.whl", hash = "sha256:063eccf89df5b24e361b123e257e437f9e9878f425ee9aae3144c77faf6da6d8", size = 3754930, upload-time = "2025-09-22T04:03:41.565Z" }, + { url = "https://files.pythonhosted.org/packages/5e/5c/42c2c4c03554580708fc738d13414801f340c04c3eff90d8d2d227145275/lxml-6.0.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:6162a86d86893d63084faaf4ff937b3daea233e3682fb4474db07395794fa80d", size = 8910380, upload-time = "2025-09-22T04:03:01.645Z" }, + { url = "https://files.pythonhosted.org/packages/bf/4f/12df843e3e10d18d468a7557058f8d3733e8b6e12401f30b1ef29360740f/lxml-6.0.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:414aaa94e974e23a3e92e7ca5b97d10c0cf37b6481f50911032c69eeb3991bba", size = 4775632, upload-time = "2025-09-22T04:03:03.814Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0c/9dc31e6c2d0d418483cbcb469d1f5a582a1cd00a1f4081953d44051f3c50/lxml-6.0.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48461bd21625458dd01e14e2c38dd0aea69addc3c4f960c30d9f59d7f93be601", size = 4975171, upload-time = "2025-09-22T04:03:05.651Z" }, + { url = "https://files.pythonhosted.org/packages/e7/2b/9b870c6ca24c841bdd887504808f0417aa9d8d564114689266f19ddf29c8/lxml-6.0.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:25fcc59afc57d527cfc78a58f40ab4c9b8fd096a9a3f964d2781ffb6eb33f4ed", size = 5110109, upload-time = "2025-09-22T04:03:07.452Z" }, + { url = "https://files.pythonhosted.org/packages/bf/0c/4f5f2a4dd319a178912751564471355d9019e220c20d7db3fb8307ed8582/lxml-6.0.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5179c60288204e6ddde3f774a93350177e08876eaf3ab78aa3a3649d43eb7d37", size = 5041061, upload-time = "2025-09-22T04:03:09.297Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/554eed290365267671fe001a20d72d14f468ae4e6acef1e179b039436967/lxml-6.0.2-cp314-cp314t-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:967aab75434de148ec80597b75062d8123cadf2943fb4281f385141e18b21338", size = 5306233, upload-time = "2025-09-22T04:03:11.651Z" }, + { url = "https://files.pythonhosted.org/packages/7a/31/1d748aa275e71802ad9722df32a7a35034246b42c0ecdd8235412c3396ef/lxml-6.0.2-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d100fcc8930d697c6561156c6810ab4a508fb264c8b6779e6e61e2ed5e7558f9", size = 5604739, upload-time = "2025-09-22T04:03:13.592Z" }, + { url = "https://files.pythonhosted.org/packages/8f/41/2c11916bcac09ed561adccacceaedd2bf0e0b25b297ea92aab99fd03d0fa/lxml-6.0.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ca59e7e13e5981175b8b3e4ab84d7da57993eeff53c07764dcebda0d0e64ecd", size = 5225119, upload-time = "2025-09-22T04:03:15.408Z" }, + { url = "https://files.pythonhosted.org/packages/99/05/4e5c2873d8f17aa018e6afde417c80cc5d0c33be4854cce3ef5670c49367/lxml-6.0.2-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:957448ac63a42e2e49531b9d6c0fa449a1970dbc32467aaad46f11545be9af1d", size = 4633665, upload-time = "2025-09-22T04:03:17.262Z" }, + { url = "https://files.pythonhosted.org/packages/0f/c9/dcc2da1bebd6275cdc723b515f93edf548b82f36a5458cca3578bc899332/lxml-6.0.2-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b7fc49c37f1786284b12af63152fe1d0990722497e2d5817acfe7a877522f9a9", size = 5234997, upload-time = "2025-09-22T04:03:19.14Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e2/5172e4e7468afca64a37b81dba152fc5d90e30f9c83c7c3213d6a02a5ce4/lxml-6.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e19e0643cc936a22e837f79d01a550678da8377d7d801a14487c10c34ee49c7e", size = 5090957, upload-time = "2025-09-22T04:03:21.436Z" }, + { url = "https://files.pythonhosted.org/packages/a5/b3/15461fd3e5cd4ddcb7938b87fc20b14ab113b92312fc97afe65cd7c85de1/lxml-6.0.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:1db01e5cf14345628e0cbe71067204db658e2fb8e51e7f33631f5f4735fefd8d", size = 4764372, upload-time = "2025-09-22T04:03:23.27Z" }, + { url = "https://files.pythonhosted.org/packages/05/33/f310b987c8bf9e61c4dd8e8035c416bd3230098f5e3cfa69fc4232de7059/lxml-6.0.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:875c6b5ab39ad5291588aed6925fac99d0097af0dd62f33c7b43736043d4a2ec", size = 5634653, upload-time = "2025-09-22T04:03:25.767Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/51c80e75e0bc9382158133bdcf4e339b5886c6ee2418b5199b3f1a61ed6d/lxml-6.0.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:cdcbed9ad19da81c480dfd6dd161886db6096083c9938ead313d94b30aadf272", size = 5233795, upload-time = "2025-09-22T04:03:27.62Z" }, + { url = "https://files.pythonhosted.org/packages/56/4d/4856e897df0d588789dd844dbed9d91782c4ef0b327f96ce53c807e13128/lxml-6.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80dadc234ebc532e09be1975ff538d154a7fa61ea5031c03d25178855544728f", size = 5257023, upload-time = "2025-09-22T04:03:30.056Z" }, + { url = "https://files.pythonhosted.org/packages/0f/85/86766dfebfa87bea0ab78e9ff7a4b4b45225df4b4d3b8cc3c03c5cd68464/lxml-6.0.2-cp314-cp314t-win32.whl", hash = "sha256:da08e7bb297b04e893d91087df19638dc7a6bb858a954b0cc2b9f5053c922312", size = 3911420, upload-time = "2025-09-22T04:03:32.198Z" }, + { url = "https://files.pythonhosted.org/packages/fe/1a/b248b355834c8e32614650b8008c69ffeb0ceb149c793961dd8c0b991bb3/lxml-6.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:252a22982dca42f6155125ac76d3432e548a7625d56f5a273ee78a5057216eca", size = 4406837, upload-time = "2025-09-22T04:03:34.027Z" }, + { url = "https://files.pythonhosted.org/packages/92/aa/df863bcc39c5e0946263454aba394de8a9084dbaff8ad143846b0d844739/lxml-6.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:bb4c1847b303835d89d785a18801a883436cdfd5dc3d62947f9c49e24f0f5a2c", size = 3822205, upload-time = "2025-09-22T04:03:36.249Z" }, +] + +[[package]] +name = "marisa-trie" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/e3/c9066e74076b90f9701ccd23d6a0b8c1d583feefdec576dc3e1bb093c50d/marisa_trie-1.3.1.tar.gz", hash = "sha256:97107fd12f30e4f8fea97790343a2d2d9a79d93697fe14e1b6f6363c984ff85b", size = 212454, upload-time = "2025-08-26T15:13:18.401Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/a2/8331b995c1b3eee83aa745f4a6502d737ec523d5955a48f167d4177db105/marisa_trie-1.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9de573d933db4753a50af891bcb3ffbfe14e200406214c223aa5dfe2163f316d", size = 172272, upload-time = "2025-08-26T15:12:24.016Z" }, + { url = "https://files.pythonhosted.org/packages/97/b8/7b9681b5c0ea1bb950f907a4e3919eb7f7b7b3febafaae346f3b3f199f6f/marisa_trie-1.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4bae4f920f2a1082eaf766c1883df7da84abdf333bafa15b8717c10416a615e", size = 154671, upload-time = "2025-08-26T15:12:25.013Z" }, + { url = "https://files.pythonhosted.org/packages/ca/16/929c1f83fdcff13f8d08500f434aaa18c21c8168d16cf81585d69085e980/marisa_trie-1.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9f2b97fcfd5e2dbb0090d0664023872dcde990df0b545eca8d0ce95795a409", size = 1238754, upload-time = "2025-08-26T15:12:26.217Z" }, + { url = "https://files.pythonhosted.org/packages/0f/0a/b0e04d3ef91a87d4c7ea0b66c004fdfc6e65c9ed83edaebecfb482dfe0ed/marisa_trie-1.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecdb19d33b26738a32602ef432b06cc6deeca4b498ce67ba8e5e39c8a7c19745", size = 1262653, upload-time = "2025-08-26T15:12:27.422Z" }, + { url = "https://files.pythonhosted.org/packages/de/1f/0ecf610ddc9a209ee63116baabb47584d5b8ecd01610091a593d9429537e/marisa_trie-1.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7416f1a084eb889c5792c57317875aeaa86abfe0bdc6f167712cebcec1d36ee", size = 2172399, upload-time = "2025-08-26T15:12:28.926Z" }, + { url = "https://files.pythonhosted.org/packages/ac/74/6b47deff3b3920449c135b9187c80f0d656adcdc5d41463745a61b012ea1/marisa_trie-1.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee428575377e29c636f2b4b3b0488875dcea310c6c5b3412ec4ef997f7bb37cc", size = 2255138, upload-time = "2025-08-26T15:12:30.271Z" }, + { url = "https://files.pythonhosted.org/packages/bd/fa/3dbcbe93dfaa626a5b3e741e7bcf3d7389aa5777175213bd8d9a9d3c992d/marisa_trie-1.3.1-cp313-cp313-win32.whl", hash = "sha256:d0f87bdf660f01e88ab3a507955697b2e3284065afa0b94fc9e77d6ad153ed5e", size = 115391, upload-time = "2025-08-26T15:12:31.465Z" }, + { url = "https://files.pythonhosted.org/packages/3b/ce/ddfab303646b21aef07ff9dbc83fba92e5d493f49d3bc03d899ffd45c86f/marisa_trie-1.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:a83f5f7ae3494e0cc25211296252b1b86901c788ed82c83adda19d0c98f828d6", size = 139130, upload-time = "2025-08-26T15:12:32.4Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1e/734b618048ad05c50cb1673ce2c6e836dc38ddeeeb011ed1804af07327a4/marisa_trie-1.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a850b151bd1e3a5d9afef113adc22727d696603659d575d7e84f994bd8d04bf1", size = 175131, upload-time = "2025-08-26T15:12:33.728Z" }, + { url = "https://files.pythonhosted.org/packages/d3/78/c7051147cc918cb8ff4a2920e11a9b17d9dcb4d8fc122122694b486e2bfe/marisa_trie-1.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9dc61fb8f8993589544f6df268229c6cf0a56ad4ed3e8585a9cd23c5ad79527b", size = 163094, upload-time = "2025-08-26T15:12:35.312Z" }, + { url = "https://files.pythonhosted.org/packages/ee/b8/3b904178d7878319aacaabae5131c1f281519aaac0f8c68c8ed312912ccf/marisa_trie-1.3.1-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4bd41a6e73c0d0adafe4de449b6d35530a4ce6a836a6ee839baf117785ecfd7", size = 1279812, upload-time = "2025-08-26T15:12:36.831Z" }, + { url = "https://files.pythonhosted.org/packages/fb/bf/e77a1284247b980560b4104bbdd5d06ed2c2ae3d56ab954f97293b6dbbcd/marisa_trie-1.3.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8c8b2386d2d22c57880ed20a913ceca86363765623175671137484a7d223f07a", size = 1285690, upload-time = "2025-08-26T15:12:38.754Z" }, + { url = "https://files.pythonhosted.org/packages/48/82/f6f10db5ec72de2642499f3a6e4e8607bbd2cfb28269ea08d0d8ddac3313/marisa_trie-1.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c56001badaf1779afae5c24b7ab85938644ab8ef3c5fd438ab5d49621b84482", size = 2197943, upload-time = "2025-08-26T15:12:40.584Z" }, + { url = "https://files.pythonhosted.org/packages/2a/d0/74b6c3011b1ebf4a8131430156b14c3af694082cf34c392fff766096fd4b/marisa_trie-1.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83a3748088d117a9b15d8981c947df9e4f56eb2e4b5456ae34fe1f83666c9185", size = 2280132, upload-time = "2025-08-26T15:12:42.059Z" }, + { url = "https://files.pythonhosted.org/packages/28/b2/b8b0cb738fa3ab07309ed92025c6e1b278f84c7255e976921a52b30d8d1b/marisa_trie-1.3.1-cp313-cp313t-win32.whl", hash = "sha256:137010598d8cebc53dbfb7caf59bde96c33a6af555e3e1bdbf30269b6a157e1e", size = 126446, upload-time = "2025-08-26T15:12:43.339Z" }, + { url = "https://files.pythonhosted.org/packages/b6/c6/2381648d0c946556ef51c673397cea40712d945444ceed0a0a0b51a174d2/marisa_trie-1.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:ec633e108f277f2b7f4671d933a909f39bba549910bf103e2940b87a14da2783", size = 153885, upload-time = "2025-08-26T15:12:44.309Z" }, + { url = "https://files.pythonhosted.org/packages/40/8a/590f25a281e08879791aabec7b8584c7934ff3d5f9d52859197d587246ec/marisa_trie-1.3.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:389721481c14a92fa042e4b91ae065bff13e2bc567c85a10aa9d9de80aaa8622", size = 172803, upload-time = "2025-08-26T15:12:45.342Z" }, + { url = "https://files.pythonhosted.org/packages/20/7f/fd19a4aa57ad169d08e518a6ee2438e7e77bfba7786c59f65891db69d202/marisa_trie-1.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e6f3b45def6ff23e254eeaa9079267004f0069d0a34eba30a620780caa4f2cb", size = 155506, upload-time = "2025-08-26T15:12:46.701Z" }, + { url = "https://files.pythonhosted.org/packages/e3/05/857832b8fe6b2ec441de1154eadc66dee067ce5fb6673c3ee0b8616108ee/marisa_trie-1.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a96ef3e461ecc85ec7d2233ddc449ff5a3fbdc520caea752bc5bc8faa975231", size = 1239979, upload-time = "2025-08-26T15:12:47.943Z" }, + { url = "https://files.pythonhosted.org/packages/4c/08/f9ea8b720a627d54e8e19f19a0ec1cc2011e01aa2b4f40d078e7f5e9e21f/marisa_trie-1.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5370f9ef6c008e502537cc1ff518c80ddf749367ce90179efa0e7f6275903a76", size = 1255705, upload-time = "2025-08-26T15:12:49.24Z" }, + { url = "https://files.pythonhosted.org/packages/e9/c3/42360fb38cdfde5db1783e2d7cfeb8b91eea837f89ef678f308ee026d794/marisa_trie-1.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0dcd42774e367ceb423c211a4fc8e7ce586acfaf0929c9c06d98002112075239", size = 2175092, upload-time = "2025-08-26T15:12:50.602Z" }, + { url = "https://files.pythonhosted.org/packages/09/ba/215b0d821fd37cdc600e834a75708aa2e117124dcf495c9a6c6dc7fdcb6b/marisa_trie-1.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3e2a0e1be95237981bd375a388f44b33d69ea5669a2f79fea038e45fff326595", size = 2250454, upload-time = "2025-08-26T15:12:52.435Z" }, + { url = "https://files.pythonhosted.org/packages/f5/a3/292ab31a12ec1cb356e6bc8b9cc8aaec920aa892a805757c011d77e8cd93/marisa_trie-1.3.1-cp314-cp314-win32.whl", hash = "sha256:c7a33506d0451112911c69f38d55da3e0e050f2be0ea4e5176865cf03baf26a9", size = 119101, upload-time = "2025-08-26T15:12:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/95/83/0ea5de53209993cf301dd9d18d4cb22c20c84c753b4357b66660a8b9eb48/marisa_trie-1.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:68678816818efcd4a1787b557af81f215b989ec88680a86c85c34c914d413690", size = 142886, upload-time = "2025-08-26T15:12:54.835Z" }, + { url = "https://files.pythonhosted.org/packages/37/00/c7e063867988067992a9d9d2aceaede0be7787ca6d77ef34f2eca9d2708e/marisa_trie-1.3.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9e467e13971c64db6aed8afe4c2a131c3f73f048bec3f788a6141216acda598d", size = 175163, upload-time = "2025-08-26T15:12:55.908Z" }, + { url = "https://files.pythonhosted.org/packages/5f/64/eaf49d10c8506ecd717bbbeda907e474842c298354a444b875741ef4a0d9/marisa_trie-1.3.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:076731f79f8603cb3216cb6e5bbbc56536c89f63f175ad47014219ecb01e5996", size = 163119, upload-time = "2025-08-26T15:12:58.054Z" }, + { url = "https://files.pythonhosted.org/packages/b4/26/f24dd9c98ce6fc8c8d554b556e1c43f326c5df414b79aba33bd7d2d2fbfd/marisa_trie-1.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82de2de90488d0fbbf74cf9f20e1afd62e320693b88f5e9565fc80b28f5bbad3", size = 1277783, upload-time = "2025-08-26T15:12:59.225Z" }, + { url = "https://files.pythonhosted.org/packages/b2/1a/efd63e75d1374e08f8ebe2e15ff1b1ed5f6d5cf57614a5b0884bd9c882ee/marisa_trie-1.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c2bc6bee737f4d47fce48c5b03a7bd3214ef2d83eb5c9f84210091370a5f195", size = 1282309, upload-time = "2025-08-26T15:13:00.797Z" }, + { url = "https://files.pythonhosted.org/packages/33/4c/0cefa1eceec7858766af5939979857ac079c6c5251e00c6991c1a26bb1b7/marisa_trie-1.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:56043cf908ddf3d7364498085dbc2855d4ea8969aff3bf2439a79482a79e68e2", size = 2196594, upload-time = "2025-08-26T15:13:02.158Z" }, + { url = "https://files.pythonhosted.org/packages/bb/64/900f4132fc345be4b40073e66284707afa4cc203d8d0f1fe78c6b111cd47/marisa_trie-1.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9651daa1fdc471df5a5fa6a4833d3b01e76ac512eea141a5995681aebac5555f", size = 2277730, upload-time = "2025-08-26T15:13:03.528Z" }, + { url = "https://files.pythonhosted.org/packages/62/ab/6d6cf25a5c8835589a601a9a916ec5cdee740e277fed8ee620df546834bb/marisa_trie-1.3.1-cp314-cp314t-win32.whl", hash = "sha256:c6571462417cda2239b1ade86ceaf3852da9b52c6286046e87d404afc6da20a7", size = 131409, upload-time = "2025-08-26T15:13:05.106Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/c4efc044141429e67e8fd5536be86d76303f250179c7f92b2cc0c72e8d0b/marisa_trie-1.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:9e6496bbad3068e3bbbb934b1e1307bf1a9cb4609f9ec47b57e8ea37f1b5ee40", size = 162564, upload-time = "2025-08-26T15:13:06.112Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, +] + +[[package]] +name = "mock" +version = "5.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/07/8c/14c2ae915e5f9dca5a22edd68b35be94400719ccfa068a03e0fb63d0f6f6/mock-5.2.0.tar.gz", hash = "sha256:4e460e818629b4b173f32d08bf30d3af8123afbb8e04bb5707a1fd4799e503f0", size = 92796, upload-time = "2025-03-03T12:31:42.911Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/d9/617e6af809bf3a1d468e0d58c3997b1dc219a9a9202e650d30c2fc85d481/mock-5.2.0-py3-none-any.whl", hash = "sha256:7ba87f72ca0e915175596069dbbcc7c75af7b5e9b9bc107ad6349ede0819982f", size = 31617, upload-time = "2025-03-03T12:31:41.518Z" }, +] + +[[package]] +name = "nose" +version = "1.3.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/a5/0dc93c3ec33f4e281849523a5a913fa1eea9a3068acfa754d44d88107a44/nose-1.3.7.tar.gz", hash = "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98", size = 280488, upload-time = "2015-06-02T09:12:32.961Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/d8/dd071918c040f50fa1cf80da16423af51ff8ce4a0f2399b7bf8de45ac3d9/nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", size = 154731, upload-time = "2015-06-02T09:12:40.57Z" }, +] + +[[package]] +name = "nose-timer" +version = "0.7.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nose" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/61/6476ed1c7a7bbb114246bb4632ec3a72008bc2d25cfbf3f4b1962143371f/nose-timer-0.7.5.tar.gz", hash = "sha256:647eeac86359188ecf02c75b0ab49d20ad10c41814ee89af30fcaf8d109b9f17", size = 7742, upload-time = "2019-03-14T04:56:36.485Z" } + +[[package]] +name = "openapi-client" +version = "1.0.0" +source = { directory = "clients/xnat/generated" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dateutil" }, + { name = "typing-extensions" }, + { name = "urllib3" }, +] + +[package.metadata] +requires-dist = [ + { name = "pydantic", specifier = ">=2" }, + { name = "python-dateutil" }, + { name = "typing-extensions", specifier = ">=4.7.1" }, + { name = "urllib3", specifier = ">=1.25.3,<2.1.0" }, +] + +[[package]] +name = "openpyxl" +version = "3.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "et-xmlfile" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/19/c45fb7a40cd46e03e36d60d1db26a50a795fa0b6b8a2a8094f4ac0c71ae5/openpyxl-3.0.9.tar.gz", hash = "sha256:40f568b9829bf9e446acfffce30250ac1fa39035124d55fc024025c41481c90f", size = 179880, upload-time = "2021-09-22T12:55:03.883Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/a6/8ce4d2ef2c29be3235c08bb00e0b81e29d38ebc47d82b17af681bf662b74/openpyxl-3.0.9-py2.py3-none-any.whl", hash = "sha256:8f3b11bd896a95468a4ab162fc4fcd260d46157155d1f8bfaabb99d88cfcf79f", size = 242160, upload-time = "2021-09-22T12:55:01.296Z" }, +] + +[[package]] +name = "outcome" +version = "1.3.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", size = 21060, upload-time = "2023-10-26T04:26:04.361Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b", size = 10692, upload-time = "2023-10-26T04:26:02.532Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "parso" +version = "0.8.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/de/53e0bcf53d13e005bd8c92e7855142494f41171b34c2536b86187474184d/parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a", size = 401205, upload-time = "2025-08-23T15:15:28.028Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668, upload-time = "2025-08-23T15:15:25.663Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + +[[package]] +name = "phonenumberslite" +version = "8.12.39" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/0e/917ea6c74108df0a74ea51835f26e0a0804982dca38f171aef5592309ff4/phonenumberslite-8.12.39.tar.gz", hash = "sha256:5b77990b6832675fa3a2e60a05e738af0bf96908352a8ee90b4d4ec964a03977", size = 269886, upload-time = "2021-12-07T14:24:36.961Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/23/839bfb413b0a3063f6734d2d663b57a823ffed31c333383630aa4a9363dc/phonenumberslite-8.12.39-py2.py3-none-any.whl", hash = "sha256:1001fd304ccf5ec7f926fd039ef07eefffa9880573698baede00a3becb8de6ad", size = 466388, upload-time = "2021-12-07T14:24:34.764Z" }, +] + +[[package]] +name = "pillow" +version = "11.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523", size = 47113069, upload-time = "2025-07-01T09:16:30.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/93/0952f2ed8db3a5a4c7a11f91965d6184ebc8cd7cbb7941a260d5f018cd2d/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd", size = 2128328, upload-time = "2025-07-01T09:14:35.276Z" }, + { url = "https://files.pythonhosted.org/packages/4b/e8/100c3d114b1a0bf4042f27e0f87d2f25e857e838034e98ca98fe7b8c0a9c/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8", size = 2170652, upload-time = "2025-07-01T09:14:37.203Z" }, + { url = "https://files.pythonhosted.org/packages/aa/86/3f758a28a6e381758545f7cdb4942e1cb79abd271bea932998fc0db93cb6/pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f", size = 2227443, upload-time = "2025-07-01T09:14:39.344Z" }, + { url = "https://files.pythonhosted.org/packages/01/f4/91d5b3ffa718df2f53b0dc109877993e511f4fd055d7e9508682e8aba092/pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c", size = 5278474, upload-time = "2025-07-01T09:14:41.843Z" }, + { url = "https://files.pythonhosted.org/packages/f9/0e/37d7d3eca6c879fbd9dba21268427dffda1ab00d4eb05b32923d4fbe3b12/pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd", size = 4686038, upload-time = "2025-07-01T09:14:44.008Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b0/3426e5c7f6565e752d81221af9d3676fdbb4f352317ceafd42899aaf5d8a/pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e", size = 5864407, upload-time = "2025-07-03T13:10:15.628Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c1/c6c423134229f2a221ee53f838d4be9d82bab86f7e2f8e75e47b6bf6cd77/pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1", size = 7639094, upload-time = "2025-07-03T13:10:21.857Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c9/09e6746630fe6372c67c648ff9deae52a2bc20897d51fa293571977ceb5d/pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805", size = 5973503, upload-time = "2025-07-01T09:14:45.698Z" }, + { url = "https://files.pythonhosted.org/packages/d5/1c/a2a29649c0b1983d3ef57ee87a66487fdeb45132df66ab30dd37f7dbe162/pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8", size = 6642574, upload-time = "2025-07-01T09:14:47.415Z" }, + { url = "https://files.pythonhosted.org/packages/36/de/d5cc31cc4b055b6c6fd990e3e7f0f8aaf36229a2698501bcb0cdf67c7146/pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2", size = 6084060, upload-time = "2025-07-01T09:14:49.636Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ea/502d938cbaeec836ac28a9b730193716f0114c41325db428e6b280513f09/pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b", size = 6721407, upload-time = "2025-07-01T09:14:51.962Z" }, + { url = "https://files.pythonhosted.org/packages/45/9c/9c5e2a73f125f6cbc59cc7087c8f2d649a7ae453f83bd0362ff7c9e2aee2/pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3", size = 6273841, upload-time = "2025-07-01T09:14:54.142Z" }, + { url = "https://files.pythonhosted.org/packages/23/85/397c73524e0cd212067e0c969aa245b01d50183439550d24d9f55781b776/pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51", size = 6978450, upload-time = "2025-07-01T09:14:56.436Z" }, + { url = "https://files.pythonhosted.org/packages/17/d2/622f4547f69cd173955194b78e4d19ca4935a1b0f03a302d655c9f6aae65/pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580", size = 2423055, upload-time = "2025-07-01T09:14:58.072Z" }, + { url = "https://files.pythonhosted.org/packages/dd/80/a8a2ac21dda2e82480852978416cfacd439a4b490a501a288ecf4fe2532d/pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e", size = 5281110, upload-time = "2025-07-01T09:14:59.79Z" }, + { url = "https://files.pythonhosted.org/packages/44/d6/b79754ca790f315918732e18f82a8146d33bcd7f4494380457ea89eb883d/pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d", size = 4689547, upload-time = "2025-07-01T09:15:01.648Z" }, + { url = "https://files.pythonhosted.org/packages/49/20/716b8717d331150cb00f7fdd78169c01e8e0c219732a78b0e59b6bdb2fd6/pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced", size = 5901554, upload-time = "2025-07-03T13:10:27.018Z" }, + { url = "https://files.pythonhosted.org/packages/74/cf/a9f3a2514a65bb071075063a96f0a5cf949c2f2fce683c15ccc83b1c1cab/pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c", size = 7669132, upload-time = "2025-07-03T13:10:33.01Z" }, + { url = "https://files.pythonhosted.org/packages/98/3c/da78805cbdbee9cb43efe8261dd7cc0b4b93f2ac79b676c03159e9db2187/pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8", size = 6005001, upload-time = "2025-07-01T09:15:03.365Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fa/ce044b91faecf30e635321351bba32bab5a7e034c60187fe9698191aef4f/pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59", size = 6668814, upload-time = "2025-07-01T09:15:05.655Z" }, + { url = "https://files.pythonhosted.org/packages/7b/51/90f9291406d09bf93686434f9183aba27b831c10c87746ff49f127ee80cb/pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe", size = 6113124, upload-time = "2025-07-01T09:15:07.358Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5a/6fec59b1dfb619234f7636d4157d11fb4e196caeee220232a8d2ec48488d/pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c", size = 6747186, upload-time = "2025-07-01T09:15:09.317Z" }, + { url = "https://files.pythonhosted.org/packages/49/6b/00187a044f98255225f172de653941e61da37104a9ea60e4f6887717e2b5/pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788", size = 6277546, upload-time = "2025-07-01T09:15:11.311Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5c/6caaba7e261c0d75bab23be79f1d06b5ad2a2ae49f028ccec801b0e853d6/pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31", size = 6985102, upload-time = "2025-07-01T09:15:13.164Z" }, + { url = "https://files.pythonhosted.org/packages/f3/7e/b623008460c09a0cb38263c93b828c666493caee2eb34ff67f778b87e58c/pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e", size = 2424803, upload-time = "2025-07-01T09:15:15.695Z" }, + { url = "https://files.pythonhosted.org/packages/73/f4/04905af42837292ed86cb1b1dabe03dce1edc008ef14c473c5c7e1443c5d/pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12", size = 5278520, upload-time = "2025-07-01T09:15:17.429Z" }, + { url = "https://files.pythonhosted.org/packages/41/b0/33d79e377a336247df6348a54e6d2a2b85d644ca202555e3faa0cf811ecc/pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a", size = 4686116, upload-time = "2025-07-01T09:15:19.423Z" }, + { url = "https://files.pythonhosted.org/packages/49/2d/ed8bc0ab219ae8768f529597d9509d184fe8a6c4741a6864fea334d25f3f/pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632", size = 5864597, upload-time = "2025-07-03T13:10:38.404Z" }, + { url = "https://files.pythonhosted.org/packages/b5/3d/b932bb4225c80b58dfadaca9d42d08d0b7064d2d1791b6a237f87f661834/pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673", size = 7638246, upload-time = "2025-07-03T13:10:44.987Z" }, + { url = "https://files.pythonhosted.org/packages/09/b5/0487044b7c096f1b48f0d7ad416472c02e0e4bf6919541b111efd3cae690/pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027", size = 5973336, upload-time = "2025-07-01T09:15:21.237Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2d/524f9318f6cbfcc79fbc004801ea6b607ec3f843977652fdee4857a7568b/pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77", size = 6642699, upload-time = "2025-07-01T09:15:23.186Z" }, + { url = "https://files.pythonhosted.org/packages/6f/d2/a9a4f280c6aefedce1e8f615baaa5474e0701d86dd6f1dede66726462bbd/pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874", size = 6083789, upload-time = "2025-07-01T09:15:25.1Z" }, + { url = "https://files.pythonhosted.org/packages/fe/54/86b0cd9dbb683a9d5e960b66c7379e821a19be4ac5810e2e5a715c09a0c0/pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a", size = 6720386, upload-time = "2025-07-01T09:15:27.378Z" }, + { url = "https://files.pythonhosted.org/packages/e7/95/88efcaf384c3588e24259c4203b909cbe3e3c2d887af9e938c2022c9dd48/pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214", size = 6370911, upload-time = "2025-07-01T09:15:29.294Z" }, + { url = "https://files.pythonhosted.org/packages/2e/cc/934e5820850ec5eb107e7b1a72dd278140731c669f396110ebc326f2a503/pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635", size = 7117383, upload-time = "2025-07-01T09:15:31.128Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e9/9c0a616a71da2a5d163aa37405e8aced9a906d574b4a214bede134e731bc/pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6", size = 2511385, upload-time = "2025-07-01T09:15:33.328Z" }, + { url = "https://files.pythonhosted.org/packages/1a/33/c88376898aff369658b225262cd4f2659b13e8178e7534df9e6e1fa289f6/pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae", size = 5281129, upload-time = "2025-07-01T09:15:35.194Z" }, + { url = "https://files.pythonhosted.org/packages/1f/70/d376247fb36f1844b42910911c83a02d5544ebd2a8bad9efcc0f707ea774/pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653", size = 4689580, upload-time = "2025-07-01T09:15:37.114Z" }, + { url = "https://files.pythonhosted.org/packages/eb/1c/537e930496149fbac69efd2fc4329035bbe2e5475b4165439e3be9cb183b/pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6", size = 5902860, upload-time = "2025-07-03T13:10:50.248Z" }, + { url = "https://files.pythonhosted.org/packages/bd/57/80f53264954dcefeebcf9dae6e3eb1daea1b488f0be8b8fef12f79a3eb10/pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36", size = 7670694, upload-time = "2025-07-03T13:10:56.432Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/4727d3b71a8578b4587d9c276e90efad2d6fe0335fd76742a6da08132e8c/pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b", size = 6005888, upload-time = "2025-07-01T09:15:39.436Z" }, + { url = "https://files.pythonhosted.org/packages/05/ae/716592277934f85d3be51d7256f3636672d7b1abfafdc42cf3f8cbd4b4c8/pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477", size = 6670330, upload-time = "2025-07-01T09:15:41.269Z" }, + { url = "https://files.pythonhosted.org/packages/e7/bb/7fe6cddcc8827b01b1a9766f5fdeb7418680744f9082035bdbabecf1d57f/pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50", size = 6114089, upload-time = "2025-07-01T09:15:43.13Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f5/06bfaa444c8e80f1a8e4bff98da9c83b37b5be3b1deaa43d27a0db37ef84/pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b", size = 6748206, upload-time = "2025-07-01T09:15:44.937Z" }, + { url = "https://files.pythonhosted.org/packages/f0/77/bc6f92a3e8e6e46c0ca78abfffec0037845800ea38c73483760362804c41/pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12", size = 6377370, upload-time = "2025-07-01T09:15:46.673Z" }, + { url = "https://files.pythonhosted.org/packages/4a/82/3a721f7d69dca802befb8af08b7c79ebcab461007ce1c18bd91a5d5896f9/pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db", size = 7121500, upload-time = "2025-07-01T09:15:48.512Z" }, + { url = "https://files.pythonhosted.org/packages/89/c7/5572fa4a3f45740eaab6ae86fcdf7195b55beac1371ac8c619d880cfe948/pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa", size = 2512835, upload-time = "2025-07-01T09:15:50.399Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "promise" +version = "2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cf/9c/fb5d48abfe5d791cd496e4242ebcf87a4bb2e0c3dcd6e0ae68c11426a528/promise-2.3.tar.gz", hash = "sha256:dfd18337c523ba4b6a58801c164c1904a9d4d1b1747c7d5dbf45b693a49d93d0", size = 19534, upload-time = "2019-12-18T07:31:43.07Z" } + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "psutil" +version = "7.1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/88/bdd0a41e5857d5d703287598cbf08dad90aed56774ea52ae071bae9071b6/psutil-7.1.3.tar.gz", hash = "sha256:6c86281738d77335af7aec228328e944b30930899ea760ecf33a4dba66be5e74", size = 489059, upload-time = "2025-11-02T12:25:54.619Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/93/0c49e776b8734fef56ec9c5c57f923922f2cf0497d62e0f419465f28f3d0/psutil-7.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0005da714eee687b4b8decd3d6cc7c6db36215c9e74e5ad2264b90c3df7d92dc", size = 239751, upload-time = "2025-11-02T12:25:58.161Z" }, + { url = "https://files.pythonhosted.org/packages/6f/8d/b31e39c769e70780f007969815195a55c81a63efebdd4dbe9e7a113adb2f/psutil-7.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:19644c85dcb987e35eeeaefdc3915d059dac7bd1167cdcdbf27e0ce2df0c08c0", size = 240368, upload-time = "2025-11-02T12:26:00.491Z" }, + { url = "https://files.pythonhosted.org/packages/62/61/23fd4acc3c9eebbf6b6c78bcd89e5d020cfde4acf0a9233e9d4e3fa698b4/psutil-7.1.3-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95ef04cf2e5ba0ab9eaafc4a11eaae91b44f4ef5541acd2ee91d9108d00d59a7", size = 287134, upload-time = "2025-11-02T12:26:02.613Z" }, + { url = "https://files.pythonhosted.org/packages/30/1c/f921a009ea9ceb51aa355cb0cc118f68d354db36eae18174bab63affb3e6/psutil-7.1.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1068c303be3a72f8e18e412c5b2a8f6d31750fb152f9cb106b54090296c9d251", size = 289904, upload-time = "2025-11-02T12:26:05.207Z" }, + { url = "https://files.pythonhosted.org/packages/a6/82/62d68066e13e46a5116df187d319d1724b3f437ddd0f958756fc052677f4/psutil-7.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:18349c5c24b06ac5612c0428ec2a0331c26443d259e2a0144a9b24b4395b58fa", size = 249642, upload-time = "2025-11-02T12:26:07.447Z" }, + { url = "https://files.pythonhosted.org/packages/df/ad/c1cd5fe965c14a0392112f68362cfceb5230819dbb5b1888950d18a11d9f/psutil-7.1.3-cp313-cp313t-win_arm64.whl", hash = "sha256:c525ffa774fe4496282fb0b1187725793de3e7c6b29e41562733cae9ada151ee", size = 245518, upload-time = "2025-11-02T12:26:09.719Z" }, + { url = "https://files.pythonhosted.org/packages/2e/bb/6670bded3e3236eb4287c7bcdc167e9fae6e1e9286e437f7111caed2f909/psutil-7.1.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b403da1df4d6d43973dc004d19cee3b848e998ae3154cc8097d139b77156c353", size = 239843, upload-time = "2025-11-02T12:26:11.968Z" }, + { url = "https://files.pythonhosted.org/packages/b8/66/853d50e75a38c9a7370ddbeefabdd3d3116b9c31ef94dc92c6729bc36bec/psutil-7.1.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad81425efc5e75da3f39b3e636293360ad8d0b49bed7df824c79764fb4ba9b8b", size = 240369, upload-time = "2025-11-02T12:26:14.358Z" }, + { url = "https://files.pythonhosted.org/packages/41/bd/313aba97cb5bfb26916dc29cf0646cbe4dd6a89ca69e8c6edce654876d39/psutil-7.1.3-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f33a3702e167783a9213db10ad29650ebf383946e91bc77f28a5eb083496bc9", size = 288210, upload-time = "2025-11-02T12:26:16.699Z" }, + { url = "https://files.pythonhosted.org/packages/c2/fa/76e3c06e760927a0cfb5705eb38164254de34e9bd86db656d4dbaa228b04/psutil-7.1.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fac9cd332c67f4422504297889da5ab7e05fd11e3c4392140f7370f4208ded1f", size = 291182, upload-time = "2025-11-02T12:26:18.848Z" }, + { url = "https://files.pythonhosted.org/packages/0f/1d/5774a91607035ee5078b8fd747686ebec28a962f178712de100d00b78a32/psutil-7.1.3-cp314-cp314t-win_amd64.whl", hash = "sha256:3792983e23b69843aea49c8f5b8f115572c5ab64c153bada5270086a2123c7e7", size = 250466, upload-time = "2025-11-02T12:26:21.183Z" }, + { url = "https://files.pythonhosted.org/packages/00/ca/e426584bacb43a5cb1ac91fae1937f478cd8fbe5e4ff96574e698a2c77cd/psutil-7.1.3-cp314-cp314t-win_arm64.whl", hash = "sha256:31d77fcedb7529f27bb3a0472bea9334349f9a04160e8e6e5020f22c59893264", size = 245756, upload-time = "2025-11-02T12:26:23.148Z" }, + { url = "https://files.pythonhosted.org/packages/ef/94/46b9154a800253e7ecff5aaacdf8ebf43db99de4a2dfa18575b02548654e/psutil-7.1.3-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2bdbcd0e58ca14996a42adf3621a6244f1bb2e2e528886959c72cf1e326677ab", size = 238359, upload-time = "2025-11-02T12:26:25.284Z" }, + { url = "https://files.pythonhosted.org/packages/68/3a/9f93cff5c025029a36d9a92fef47220ab4692ee7f2be0fba9f92813d0cb8/psutil-7.1.3-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31fa00f1fbc3c3802141eede66f3a2d51d89716a194bf2cd6fc68310a19880", size = 239171, upload-time = "2025-11-02T12:26:27.23Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b1/5f49af514f76431ba4eea935b8ad3725cdeb397e9245ab919dbc1d1dc20f/psutil-7.1.3-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb428f9f05c1225a558f53e30ccbad9930b11c3fc206836242de1091d3e7dd3", size = 263261, upload-time = "2025-11-02T12:26:29.48Z" }, + { url = "https://files.pythonhosted.org/packages/e0/95/992c8816a74016eb095e73585d747e0a8ea21a061ed3689474fabb29a395/psutil-7.1.3-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d974e02ca2c8eb4812c3f76c30e28836fffc311d55d979f1465c1feeb2b68b", size = 264635, upload-time = "2025-11-02T12:26:31.74Z" }, + { url = "https://files.pythonhosted.org/packages/55/4c/c3ed1a622b6ae2fd3c945a366e64eb35247a31e4db16cf5095e269e8eb3c/psutil-7.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:f39c2c19fe824b47484b96f9692932248a54c43799a84282cfe58d05a6449efd", size = 247633, upload-time = "2025-11-02T12:26:33.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ad/33b2ccec09bf96c2b2ef3f9a6f66baac8253d7565d8839e024a6b905d45d/psutil-7.1.3-cp37-abi3-win_arm64.whl", hash = "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1", size = 244608, upload-time = "2025-11-02T12:26:36.136Z" }, +] + +[[package]] +name = "psycopg2-binary" +version = "2.9.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/0e/bdc8274dc0585090b4e3432267d7be4dfbfd8971c0fa59167c711105a6bf/psycopg2-binary-2.9.10.tar.gz", hash = "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2", size = 385764, upload-time = "2024-10-16T11:24:58.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/30/d41d3ba765609c0763505d565c4d12d8f3c79793f0d0f044ff5a28bf395b/psycopg2_binary-2.9.10-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d", size = 3044699, upload-time = "2024-10-16T11:21:42.841Z" }, + { url = "https://files.pythonhosted.org/packages/35/44/257ddadec7ef04536ba71af6bc6a75ec05c5343004a7ec93006bee66c0bc/psycopg2_binary-2.9.10-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb", size = 3275245, upload-time = "2024-10-16T11:21:51.989Z" }, + { url = "https://files.pythonhosted.org/packages/1b/11/48ea1cd11de67f9efd7262085588790a95d9dfcd9b8a687d46caf7305c1a/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7", size = 2851631, upload-time = "2024-10-16T11:21:57.584Z" }, + { url = "https://files.pythonhosted.org/packages/62/e0/62ce5ee650e6c86719d621a761fe4bc846ab9eff8c1f12b1ed5741bf1c9b/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d", size = 3082140, upload-time = "2024-10-16T11:22:02.005Z" }, + { url = "https://files.pythonhosted.org/packages/27/ce/63f946c098611f7be234c0dd7cb1ad68b0b5744d34f68062bb3c5aa510c8/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73", size = 3264762, upload-time = "2024-10-16T11:22:06.412Z" }, + { url = "https://files.pythonhosted.org/packages/43/25/c603cd81402e69edf7daa59b1602bd41eb9859e2824b8c0855d748366ac9/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673", size = 3020967, upload-time = "2024-10-16T11:22:11.583Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d6/8708d8c6fca531057fa170cdde8df870e8b6a9b136e82b361c65e42b841e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f", size = 2872326, upload-time = "2024-10-16T11:22:16.406Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ac/5b1ea50fc08a9df82de7e1771537557f07c2632231bbab652c7e22597908/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909", size = 2822712, upload-time = "2024-10-16T11:22:21.366Z" }, + { url = "https://files.pythonhosted.org/packages/c4/fc/504d4503b2abc4570fac3ca56eb8fed5e437bf9c9ef13f36b6621db8ef00/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1", size = 2920155, upload-time = "2024-10-16T11:22:25.684Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d1/323581e9273ad2c0dbd1902f3fb50c441da86e894b6e25a73c3fda32c57e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567", size = 2959356, upload-time = "2024-10-16T11:22:30.562Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/d13ea0a054189ae1bc21af1d85b6f8bb9bbc5572991055d70ad9006fe2d6/psycopg2_binary-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142", size = 2569224, upload-time = "2025-01-04T20:09:19.234Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "py" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/ff/fec109ceb715d2a6b4c4a85a61af3b40c723a961e8828319fbcb15b868dc/py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", size = 207796, upload-time = "2021-11-04T17:17:01.377Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378", size = 98708, upload-time = "2021-11-04T17:17:00.152Z" }, +] + +[[package]] +name = "pycodestyle" +version = "2.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/e0/abfd2a0d2efe47670df87f3e3a0e2edda42f055053c85361f19c0e2c1ca8/pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", size = 39472, upload-time = "2025-06-20T18:49:48.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d", size = 31594, upload-time = "2025-06-20T18:49:47.491Z" }, +] + +[[package]] +name = "pycountry" +version = "22.1.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/03/c4/2db520ae518156a88b419b2865d4fdc85fe78573948358f79dbaf0cf2b30/pycountry-22.1.10.tar.gz", hash = "sha256:b9a6d9cdbf53f81ccdf73f6f5de01b0d8493cab2213a230af3e34458de85ea32", size = 10060795, upload-time = "2022-01-10T07:40:43.133Z" } + +[[package]] +name = "pycparser" +version = "2.23" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, +] + +[[package]] +name = "pydantic" +version = "2.12.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, + { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, + { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, + { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, + { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, + { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, + { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, + { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, + { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, + { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, + { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, + { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, + { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, + { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, + { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pynose" +version = "1.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/ad/1b5d064d53a3cc33999649c5f3b0e7cee739e7404a30bb7efd1443604a7c/pynose-1.5.5.tar.gz", hash = "sha256:81da4e26473f98dd37497248eef4352d3221d1d56edf874a00c6bdda6daf7f49", size = 123419, upload-time = "2025-09-08T20:45:15.595Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/29/02/70dd00c947bcb4a1e9f883761aa4632a9d61b5bf5f5ad4fae5e8cb06200c/pynose-1.5.5-py3-none-any.whl", hash = "sha256:673751d53fcfc79b1e48c14f36c7a24779ad43676eeb85736934de6a2b3d8ec8", size = 130706, upload-time = "2025-09-08T20:45:13.697Z" }, +] + +[[package]] +name = "pyopenssl" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/be/97b83a464498a79103036bc74d1038df4a7ef0e402cfaf4d5e113fb14759/pyopenssl-25.3.0.tar.gz", hash = "sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329", size = 184073, upload-time = "2025-09-17T00:32:21.037Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/81/ef2b1dfd1862567d573a4fdbc9f969067621764fbb74338496840a1d2977/pyopenssl-25.3.0-py3-none-any.whl", hash = "sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6", size = 57268, upload-time = "2025-09-17T00:32:19.474Z" }, +] + +[[package]] +name = "pyrsistent" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/3a/5031723c09068e9c8c2f0bc25c3a9245f2b1d1aea8396c787a408f2b95ca/pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4", size = 103642, upload-time = "2023-10-25T21:06:56.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/88/0acd180010aaed4987c85700b7cc17f9505f3edb4e5873e4dc67f613e338/pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b", size = 58106, upload-time = "2023-10-25T21:06:54.387Z" }, +] + +[[package]] +name = "pysocks" +version = "1.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0", size = 284429, upload-time = "2019-09-20T02:07:35.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", size = 16725, upload-time = "2019-09-20T02:06:22.938Z" }, +] + +[[package]] +name = "pytest" +version = "7.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "atomicwrites", marker = "sys_platform == 'win32'" }, + { name = "attrs" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "py" }, + { name = "tomli" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f0/8c/1fb22b4e526a7461b4797042ed9d9c26a7a69673a148709bf50692b874fb/pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63", size = 1255528, upload-time = "2022-03-17T21:15:03.676Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/ac/556e4410326ce77eeb1d1ec35a3e3ec847fb3e5cb30673729d2eeeffc970/pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea", size = 297001, upload-time = "2022-03-17T21:15:01.04Z" }, +] + +[[package]] +name = "pytest-django" +version = "4.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/42/6d6563165b82289d4a30ea477f85c04386303e51cf4e4e4651d4f9910830/pytest-django-4.5.2.tar.gz", hash = "sha256:d9076f759bb7c36939dbdd5ae6633c18edfc2902d1a69fdbefd2426b970ce6c2", size = 79949, upload-time = "2021-12-07T14:26:58.991Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/21/b65ecd6686da400e2f6e3c49c2a428325abd979c9670cd97e1671f53296e/pytest_django-4.5.2-py3-none-any.whl", hash = "sha256:c60834861933773109334fe5a53e83d1ef4828f2203a1d6a0fa9972f4f75ab3e", size = 20752, upload-time = "2021-12-07T14:26:57.714Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/c4/13b4776ea2d76c115c1d1b84579f3764ee6d57204f6be27119f13a61d0a9/python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", size = 357324, upload-time = "2021-07-14T08:19:19.783Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/7a/87837f39d0296e723bb9b62bbb257d0355c7f6128853c78955f57342a56d/python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9", size = 247702, upload-time = "2021-07-14T08:19:18.161Z" }, +] + +[[package]] +name = "python-levenshtein" +version = "0.27.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "levenshtein" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/b4/36eda4188dd19d3cb53d8a8749d7520bd23dfe1c1f44e56ea9dcd0232274/python_levenshtein-0.27.3.tar.gz", hash = "sha256:27dc2d65aeb62a7d6852388f197073296370779286c0860b087357f3b8129a62", size = 12446, upload-time = "2025-11-01T12:54:59.712Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/5b/26e3cca2589252ceabf964ba81514e6f48556553c9c2766e1a0fdceec696/python_levenshtein-0.27.3-py3-none-any.whl", hash = "sha256:5d6168a8e8befb25abf04d2952368a446722be10e8ced218d0dc4fd3703a43a1", size = 9504, upload-time = "2025-11-01T12:54:58.933Z" }, +] + +[[package]] +name = "python-magic" +version = "0.4.24" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/70/76b185393fecf78f81c12f9dc7b1df814df785f6acb545fc92b016e75a7e/python-magic-0.4.24.tar.gz", hash = "sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf", size = 17295, upload-time = "2021-06-03T13:49:24.116Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/99/c89223c6547df268596899334ee77b3051f606077317023617b1c43162fb/python_magic-0.4.24-py2.py3-none-any.whl", hash = "sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626", size = 12785, upload-time = "2021-06-03T13:49:22.828Z" }, +] + +[[package]] +name = "pytz" +version = "2025.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, +] + +[[package]] +name = "pyvirtualdisplay" +version = "0.2.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "easyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1e/7c/28b48481c8992727ac90526bb4395b76081b6df8265835a6d6a478c7e2c9/PyVirtualDisplay-0.2.5.tar.gz", hash = "sha256:5b267c8ffc98fcbd084ba852ab4caef3f22e9362bc5d117e1697e767553eaf41", size = 32471, upload-time = "2019-12-18T17:20:16.963Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/ec/8221a07850d69fa3c57c02e526edd23d18c7c05d58ed103e3b19172757c1/PyVirtualDisplay-0.2.5-py2.py3-none-any.whl", hash = "sha256:cab4ce130be34a9f62b402954451e829035616d39d7a1ba485dabbf77afb9fb4", size = 13712, upload-time = "2019-12-18T17:20:14.902Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "qrcode" +version = "6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/d5/6c7d4e103d94364d067636417a77a6024219c58cd6e9f428ece9b5061ef9/qrcode-6.1.tar.gz", hash = "sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369", size = 29363, upload-time = "2019-01-14T00:21:17.8Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/87/4a3a77e59ab7493d64da1f69bf1c2e899a4cf81e51b2baa855e8cc8115be/qrcode-6.1-py2.py3-none-any.whl", hash = "sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5", size = 31073, upload-time = "2019-01-14T00:21:15.271Z" }, +] + +[[package]] +name = "rapidfuzz" +version = "3.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/28/9d808fe62375b9aab5ba92fa9b29371297b067c2790b2d7cda648b1e2f8d/rapidfuzz-3.14.3.tar.gz", hash = "sha256:2491937177868bc4b1e469087601d53f925e8d270ccc21e07404b4b5814b7b5f", size = 57863900, upload-time = "2025-11-01T11:54:52.321Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/4f/0d94d09646853bd26978cb3a7541b6233c5760687777fa97da8de0d9a6ac/rapidfuzz-3.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dbcb726064b12f356bf10fffdb6db4b6dce5390b23627c08652b3f6e49aa56ae", size = 1939646, upload-time = "2025-11-01T11:53:25.292Z" }, + { url = "https://files.pythonhosted.org/packages/b6/eb/f96aefc00f3bbdbab9c0657363ea8437a207d7545ac1c3789673e05d80bd/rapidfuzz-3.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1704fc70d214294e554a2421b473779bcdeef715881c5e927dc0f11e1692a0ff", size = 1385512, upload-time = "2025-11-01T11:53:27.594Z" }, + { url = "https://files.pythonhosted.org/packages/26/34/71c4f7749c12ee223dba90017a5947e8f03731a7cc9f489b662a8e9e643d/rapidfuzz-3.14.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc65e72790ddfd310c2c8912b45106e3800fefe160b0c2ef4d6b6fec4e826457", size = 1373571, upload-time = "2025-11-01T11:53:29.096Z" }, + { url = "https://files.pythonhosted.org/packages/32/00/ec8597a64f2be301ce1ee3290d067f49f6a7afb226b67d5f15b56d772ba5/rapidfuzz-3.14.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e38c1305cffae8472572a0584d4ffc2f130865586a81038ca3965301f7c97c", size = 3156759, upload-time = "2025-11-01T11:53:30.777Z" }, + { url = "https://files.pythonhosted.org/packages/61/d5/b41eeb4930501cc899d5a9a7b5c9a33d85a670200d7e81658626dcc0ecc0/rapidfuzz-3.14.3-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:e195a77d06c03c98b3fc06b8a28576ba824392ce40de8c708f96ce04849a052e", size = 1222067, upload-time = "2025-11-01T11:53:32.334Z" }, + { url = "https://files.pythonhosted.org/packages/2a/7d/6d9abb4ffd1027c6ed837b425834f3bed8344472eb3a503ab55b3407c721/rapidfuzz-3.14.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1b7ef2f4b8583a744338a18f12c69693c194fb6777c0e9ada98cd4d9e8f09d10", size = 2394775, upload-time = "2025-11-01T11:53:34.24Z" }, + { url = "https://files.pythonhosted.org/packages/15/ce/4f3ab4c401c5a55364da1ffff8cc879fc97b4e5f4fa96033827da491a973/rapidfuzz-3.14.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a2135b138bcdcb4c3742d417f215ac2d8c2b87bde15b0feede231ae95f09ec41", size = 2526123, upload-time = "2025-11-01T11:53:35.779Z" }, + { url = "https://files.pythonhosted.org/packages/c1/4b/54f804975376a328f57293bd817c12c9036171d15cf7292032e3f5820b2d/rapidfuzz-3.14.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:33a325ed0e8e1aa20c3e75f8ab057a7b248fdea7843c2a19ade0008906c14af0", size = 4262874, upload-time = "2025-11-01T11:53:37.866Z" }, + { url = "https://files.pythonhosted.org/packages/e9/b6/958db27d8a29a50ee6edd45d33debd3ce732e7209183a72f57544cd5fe22/rapidfuzz-3.14.3-cp313-cp313-win32.whl", hash = "sha256:8383b6d0d92f6cd008f3c9216535be215a064b2cc890398a678b56e6d280cb63", size = 1707972, upload-time = "2025-11-01T11:53:39.442Z" }, + { url = "https://files.pythonhosted.org/packages/07/75/fde1f334b0cec15b5946d9f84d73250fbfcc73c236b4bc1b25129d90876b/rapidfuzz-3.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:e6b5e3036976f0fde888687d91be86d81f9ac5f7b02e218913c38285b756be6c", size = 1537011, upload-time = "2025-11-01T11:53:40.92Z" }, + { url = "https://files.pythonhosted.org/packages/2e/d7/d83fe001ce599dc7ead57ba1debf923dc961b6bdce522b741e6b8c82f55c/rapidfuzz-3.14.3-cp313-cp313-win_arm64.whl", hash = "sha256:7ba009977601d8b0828bfac9a110b195b3e4e79b350dcfa48c11269a9f1918a0", size = 810744, upload-time = "2025-11-01T11:53:42.723Z" }, + { url = "https://files.pythonhosted.org/packages/92/13/a486369e63ff3c1a58444d16b15c5feb943edd0e6c28a1d7d67cb8946b8f/rapidfuzz-3.14.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0a28add871425c2fe94358c6300bbeb0bc2ed828ca003420ac6825408f5a424", size = 1967702, upload-time = "2025-11-01T11:53:44.554Z" }, + { url = "https://files.pythonhosted.org/packages/f1/82/efad25e260b7810f01d6b69122685e355bed78c94a12784bac4e0beb2afb/rapidfuzz-3.14.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:010e12e2411a4854b0434f920e72b717c43f8ec48d57e7affe5c42ecfa05dd0e", size = 1410702, upload-time = "2025-11-01T11:53:46.066Z" }, + { url = "https://files.pythonhosted.org/packages/ba/1a/34c977b860cde91082eae4a97ae503f43e0d84d4af301d857679b66f9869/rapidfuzz-3.14.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cfc3d57abd83c734d1714ec39c88a34dd69c85474918ebc21296f1e61eb5ca8", size = 1382337, upload-time = "2025-11-01T11:53:47.62Z" }, + { url = "https://files.pythonhosted.org/packages/88/74/f50ea0e24a5880a9159e8fd256b84d8f4634c2f6b4f98028bdd31891d907/rapidfuzz-3.14.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89acb8cbb52904f763e5ac238083b9fc193bed8d1f03c80568b20e4cef43a519", size = 3165563, upload-time = "2025-11-01T11:53:49.216Z" }, + { url = "https://files.pythonhosted.org/packages/e8/7a/e744359404d7737049c26099423fc54bcbf303de5d870d07d2fb1410f567/rapidfuzz-3.14.3-cp313-cp313t-manylinux_2_31_armv7l.whl", hash = "sha256:7d9af908c2f371bfb9c985bd134e295038e3031e666e4b2ade1e7cb7f5af2f1a", size = 1214727, upload-time = "2025-11-01T11:53:50.883Z" }, + { url = "https://files.pythonhosted.org/packages/d3/2e/87adfe14ce75768ec6c2b8acd0e05e85e84be4be5e3d283cdae360afc4fe/rapidfuzz-3.14.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1f1925619627f8798f8c3a391d81071336942e5fe8467bc3c567f982e7ce2897", size = 2403349, upload-time = "2025-11-01T11:53:52.322Z" }, + { url = "https://files.pythonhosted.org/packages/70/17/6c0b2b2bff9c8b12e12624c07aa22e922b0c72a490f180fa9183d1ef2c75/rapidfuzz-3.14.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:152555187360978119e98ce3e8263d70dd0c40c7541193fc302e9b7125cf8f58", size = 2507596, upload-time = "2025-11-01T11:53:53.835Z" }, + { url = "https://files.pythonhosted.org/packages/c3/d1/87852a7cbe4da7b962174c749a47433881a63a817d04f3e385ea9babcd9e/rapidfuzz-3.14.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:52619d25a09546b8db078981ca88939d72caa6b8701edd8b22e16482a38e799f", size = 4273595, upload-time = "2025-11-01T11:53:55.961Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ab/1d0354b7d1771a28fa7fe089bc23acec2bdd3756efa2419f463e3ed80e16/rapidfuzz-3.14.3-cp313-cp313t-win32.whl", hash = "sha256:489ce98a895c98cad284f0a47960c3e264c724cb4cfd47a1430fa091c0c25204", size = 1757773, upload-time = "2025-11-01T11:53:57.628Z" }, + { url = "https://files.pythonhosted.org/packages/0b/0c/71ef356adc29e2bdf74cd284317b34a16b80258fa0e7e242dd92cc1e6d10/rapidfuzz-3.14.3-cp313-cp313t-win_amd64.whl", hash = "sha256:656e52b054d5b5c2524169240e50cfa080b04b1c613c5f90a2465e84888d6f15", size = 1576797, upload-time = "2025-11-01T11:53:59.455Z" }, + { url = "https://files.pythonhosted.org/packages/fe/d2/0e64fc27bb08d4304aa3d11154eb5480bcf5d62d60140a7ee984dc07468a/rapidfuzz-3.14.3-cp313-cp313t-win_arm64.whl", hash = "sha256:c7e40c0a0af02ad6e57e89f62bef8604f55a04ecae90b0ceeda591bbf5923317", size = 829940, upload-time = "2025-11-01T11:54:01.1Z" }, + { url = "https://files.pythonhosted.org/packages/32/6f/1b88aaeade83abc5418788f9e6b01efefcd1a69d65ded37d89cd1662be41/rapidfuzz-3.14.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:442125473b247227d3f2de807a11da6c08ccf536572d1be943f8e262bae7e4ea", size = 1942086, upload-time = "2025-11-01T11:54:02.592Z" }, + { url = "https://files.pythonhosted.org/packages/a0/2c/b23861347436cb10f46c2bd425489ec462790faaa360a54a7ede5f78de88/rapidfuzz-3.14.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ec0c8c0c3d4f97ced46b2e191e883f8c82dbbf6d5ebc1842366d7eff13cd5a6", size = 1386993, upload-time = "2025-11-01T11:54:04.12Z" }, + { url = "https://files.pythonhosted.org/packages/83/86/5d72e2c060aa1fbdc1f7362d938f6b237dff91f5b9fc5dd7cc297e112250/rapidfuzz-3.14.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2dc37bc20272f388b8c3a4eba4febc6e77e50a8f450c472def4751e7678f55e4", size = 1379126, upload-time = "2025-11-01T11:54:05.777Z" }, + { url = "https://files.pythonhosted.org/packages/c9/bc/ef2cee3e4d8b3fc22705ff519f0d487eecc756abdc7c25d53686689d6cf2/rapidfuzz-3.14.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dee362e7e79bae940a5e2b3f6d09c6554db6a4e301cc68343886c08be99844f1", size = 3159304, upload-time = "2025-11-01T11:54:07.351Z" }, + { url = "https://files.pythonhosted.org/packages/a0/36/dc5f2f62bbc7bc90be1f75eeaf49ed9502094bb19290dfb4747317b17f12/rapidfuzz-3.14.3-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:4b39921df948388a863f0e267edf2c36302983459b021ab928d4b801cbe6a421", size = 1218207, upload-time = "2025-11-01T11:54:09.641Z" }, + { url = "https://files.pythonhosted.org/packages/df/7e/8f4be75c1bc62f47edf2bbbe2370ee482fae655ebcc4718ac3827ead3904/rapidfuzz-3.14.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:beda6aa9bc44d1d81242e7b291b446be352d3451f8217fcb068fc2933927d53b", size = 2401245, upload-time = "2025-11-01T11:54:11.543Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/f7c92759e1bb188dd05b80d11c630ba59b8d7856657baf454ff56059c2ab/rapidfuzz-3.14.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:6a014ba09657abfcfeed64b7d09407acb29af436d7fc075b23a298a7e4a6b41c", size = 2518308, upload-time = "2025-11-01T11:54:13.134Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ac/85820f70fed5ecb5f1d9a55f1e1e2090ef62985ef41db289b5ac5ec56e28/rapidfuzz-3.14.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:32eeafa3abce138bb725550c0e228fc7eaeec7059aa8093d9cbbec2b58c2371a", size = 4265011, upload-time = "2025-11-01T11:54:15.087Z" }, + { url = "https://files.pythonhosted.org/packages/46/a9/616930721ea9835c918af7cde22bff17f9db3639b0c1a7f96684be7f5630/rapidfuzz-3.14.3-cp314-cp314-win32.whl", hash = "sha256:adb44d996fc610c7da8c5048775b21db60dd63b1548f078e95858c05c86876a3", size = 1742245, upload-time = "2025-11-01T11:54:17.19Z" }, + { url = "https://files.pythonhosted.org/packages/06/8a/f2fa5e9635b1ccafda4accf0e38246003f69982d7c81f2faa150014525a4/rapidfuzz-3.14.3-cp314-cp314-win_amd64.whl", hash = "sha256:f3d15d8527e2b293e38ce6e437631af0708df29eafd7c9fc48210854c94472f9", size = 1584856, upload-time = "2025-11-01T11:54:18.764Z" }, + { url = "https://files.pythonhosted.org/packages/ef/97/09e20663917678a6d60d8e0e29796db175b1165e2079830430342d5298be/rapidfuzz-3.14.3-cp314-cp314-win_arm64.whl", hash = "sha256:576e4b9012a67e0bf54fccb69a7b6c94d4e86a9540a62f1a5144977359133583", size = 833490, upload-time = "2025-11-01T11:54:20.753Z" }, + { url = "https://files.pythonhosted.org/packages/03/1b/6b6084576ba87bf21877c77218a0c97ba98cb285b0c02eaaee3acd7c4513/rapidfuzz-3.14.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:cec3c0da88562727dd5a5a364bd9efeb535400ff0bfb1443156dd139a1dd7b50", size = 1968658, upload-time = "2025-11-01T11:54:22.25Z" }, + { url = "https://files.pythonhosted.org/packages/38/c0/fb02a0db80d95704b0a6469cc394e8c38501abf7e1c0b2afe3261d1510c2/rapidfuzz-3.14.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d1fa009f8b1100e4880868137e7bf0501422898f7674f2adcd85d5a67f041296", size = 1410742, upload-time = "2025-11-01T11:54:23.863Z" }, + { url = "https://files.pythonhosted.org/packages/a4/72/3fbf12819fc6afc8ec75a45204013b40979d068971e535a7f3512b05e765/rapidfuzz-3.14.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b86daa7419b5e8b180690efd1fdbac43ff19230803282521c5b5a9c83977655", size = 1382810, upload-time = "2025-11-01T11:54:25.571Z" }, + { url = "https://files.pythonhosted.org/packages/0f/18/0f1991d59bb7eee28922a00f79d83eafa8c7bfb4e8edebf4af2a160e7196/rapidfuzz-3.14.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7bd1816db05d6c5ffb3a4df0a2b7b56fb8c81ef584d08e37058afa217da91b1", size = 3166349, upload-time = "2025-11-01T11:54:27.195Z" }, + { url = "https://files.pythonhosted.org/packages/0d/f0/baa958b1989c8f88c78bbb329e969440cf330b5a01a982669986495bb980/rapidfuzz-3.14.3-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:33da4bbaf44e9755b0ce192597f3bde7372fe2e381ab305f41b707a95ac57aa7", size = 1214994, upload-time = "2025-11-01T11:54:28.821Z" }, + { url = "https://files.pythonhosted.org/packages/e4/a0/cd12ec71f9b2519a3954febc5740291cceabc64c87bc6433afcb36259f3b/rapidfuzz-3.14.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3fecce764cf5a991ee2195a844196da840aba72029b2612f95ac68a8b74946bf", size = 2403919, upload-time = "2025-11-01T11:54:30.393Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ce/019bd2176c1644098eced4f0595cb4b3ef52e4941ac9a5854f209d0a6e16/rapidfuzz-3.14.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:ecd7453e02cf072258c3a6b8e930230d789d5d46cc849503729f9ce475d0e785", size = 2508346, upload-time = "2025-11-01T11:54:32.048Z" }, + { url = "https://files.pythonhosted.org/packages/23/f8/be16c68e2c9e6c4f23e8f4adbb7bccc9483200087ed28ff76c5312da9b14/rapidfuzz-3.14.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea188aa00e9bcae8c8411f006a5f2f06c4607a02f24eab0d8dc58566aa911f35", size = 4274105, upload-time = "2025-11-01T11:54:33.701Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d1/5ab148e03f7e6ec8cd220ccf7af74d3aaa4de26dd96df58936beb7cba820/rapidfuzz-3.14.3-cp314-cp314t-win32.whl", hash = "sha256:7ccbf68100c170e9a0581accbe9291850936711548c6688ce3bfb897b8c589ad", size = 1793465, upload-time = "2025-11-01T11:54:35.331Z" }, + { url = "https://files.pythonhosted.org/packages/cd/97/433b2d98e97abd9fff1c470a109b311669f44cdec8d0d5aa250aceaed1fb/rapidfuzz-3.14.3-cp314-cp314t-win_amd64.whl", hash = "sha256:9ec02e62ae765a318d6de38df609c57fc6dacc65c0ed1fd489036834fd8a620c", size = 1623491, upload-time = "2025-11-01T11:54:38.085Z" }, + { url = "https://files.pythonhosted.org/packages/e2/f6/e2176eb94f94892441bce3ddc514c179facb65db245e7ce3356965595b19/rapidfuzz-3.14.3-cp314-cp314t-win_arm64.whl", hash = "sha256:e805e52322ae29aa945baf7168b6c898120fbc16d2b8f940b658a5e9e3999253", size = 851487, upload-time = "2025-11-01T11:54:40.176Z" }, +] + +[[package]] +name = "requests" +version = "2.32.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, +] + +[[package]] +name = "roman-numerals" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/f9/41dc953bbeb056c17d5f7a519f50fdf010bd0553be2d630bc69d1e022703/roman_numerals-4.1.0.tar.gz", hash = "sha256:1af8b147eb1405d5839e78aeb93131690495fe9da5c91856cb33ad55a7f1e5b2", size = 9077, upload-time = "2025-12-17T18:25:34.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/54/6f679c435d28e0a568d8e8a7c0a93a09010818634c3c3907fc98d8983770/roman_numerals-4.1.0-py3-none-any.whl", hash = "sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7", size = 7676, upload-time = "2025-12-17T18:25:33.098Z" }, +] + +[[package]] +name = "ruff" +version = "0.14.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/08/52232a877978dd8f9cf2aeddce3e611b40a63287dfca29b6b8da791f5e8d/ruff-0.14.10.tar.gz", hash = "sha256:9a2e830f075d1a42cd28420d7809ace390832a490ed0966fe373ba288e77aaf4", size = 5859763, upload-time = "2025-12-18T19:28:57.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/01/933704d69f3f05ee16ef11406b78881733c186fe14b6a46b05cfcaf6d3b2/ruff-0.14.10-py3-none-linux_armv6l.whl", hash = "sha256:7a3ce585f2ade3e1f29ec1b92df13e3da262178df8c8bdf876f48fa0e8316c49", size = 13527080, upload-time = "2025-12-18T19:29:25.642Z" }, + { url = "https://files.pythonhosted.org/packages/df/58/a0349197a7dfa603ffb7f5b0470391efa79ddc327c1e29c4851e85b09cc5/ruff-0.14.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:674f9be9372907f7257c51f1d4fc902cb7cf014b9980152b802794317941f08f", size = 13797320, upload-time = "2025-12-18T19:29:02.571Z" }, + { url = "https://files.pythonhosted.org/packages/7b/82/36be59f00a6082e38c23536df4e71cdbc6af8d7c707eade97fcad5c98235/ruff-0.14.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d85713d522348837ef9df8efca33ccb8bd6fcfc86a2cde3ccb4bc9d28a18003d", size = 12918434, upload-time = "2025-12-18T19:28:51.202Z" }, + { url = "https://files.pythonhosted.org/packages/a6/00/45c62a7f7e34da92a25804f813ebe05c88aa9e0c25e5cb5a7d23dd7450e3/ruff-0.14.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6987ebe0501ae4f4308d7d24e2d0fe3d7a98430f5adfd0f1fead050a740a3a77", size = 13371961, upload-time = "2025-12-18T19:29:04.991Z" }, + { url = "https://files.pythonhosted.org/packages/40/31/a5906d60f0405f7e57045a70f2d57084a93ca7425f22e1d66904769d1628/ruff-0.14.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16a01dfb7b9e4eee556fbfd5392806b1b8550c9b4a9f6acd3dbe6812b193c70a", size = 13275629, upload-time = "2025-12-18T19:29:21.381Z" }, + { url = "https://files.pythonhosted.org/packages/3e/60/61c0087df21894cf9d928dc04bcd4fb10e8b2e8dca7b1a276ba2155b2002/ruff-0.14.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7165d31a925b7a294465fa81be8c12a0e9b60fb02bf177e79067c867e71f8b1f", size = 14029234, upload-time = "2025-12-18T19:29:00.132Z" }, + { url = "https://files.pythonhosted.org/packages/44/84/77d911bee3b92348b6e5dab5a0c898d87084ea03ac5dc708f46d88407def/ruff-0.14.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c561695675b972effb0c0a45db233f2c816ff3da8dcfbe7dfc7eed625f218935", size = 15449890, upload-time = "2025-12-18T19:28:53.573Z" }, + { url = "https://files.pythonhosted.org/packages/e9/36/480206eaefa24a7ec321582dda580443a8f0671fdbf6b1c80e9c3e93a16a/ruff-0.14.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb98fcbbc61725968893682fd4df8966a34611239c9fd07a1f6a07e7103d08e", size = 15123172, upload-time = "2025-12-18T19:29:23.453Z" }, + { url = "https://files.pythonhosted.org/packages/5c/38/68e414156015ba80cef5473d57919d27dfb62ec804b96180bafdeaf0e090/ruff-0.14.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f24b47993a9d8cb858429e97bdf8544c78029f09b520af615c1d261bf827001d", size = 14460260, upload-time = "2025-12-18T19:29:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/b3/19/9e050c0dca8aba824d67cc0db69fb459c28d8cd3f6855b1405b3f29cc91d/ruff-0.14.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59aabd2e2c4fd614d2862e7939c34a532c04f1084476d6833dddef4afab87e9f", size = 14229978, upload-time = "2025-12-18T19:29:11.32Z" }, + { url = "https://files.pythonhosted.org/packages/51/eb/e8dd1dd6e05b9e695aa9dd420f4577debdd0f87a5ff2fedda33c09e9be8c/ruff-0.14.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:213db2b2e44be8625002dbea33bb9c60c66ea2c07c084a00d55732689d697a7f", size = 14338036, upload-time = "2025-12-18T19:29:09.184Z" }, + { url = "https://files.pythonhosted.org/packages/6a/12/f3e3a505db7c19303b70af370d137795fcfec136d670d5de5391e295c134/ruff-0.14.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b914c40ab64865a17a9a5b67911d14df72346a634527240039eb3bd650e5979d", size = 13264051, upload-time = "2025-12-18T19:29:13.431Z" }, + { url = "https://files.pythonhosted.org/packages/08/64/8c3a47eaccfef8ac20e0484e68e0772013eb85802f8a9f7603ca751eb166/ruff-0.14.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1484983559f026788e3a5c07c81ef7d1e97c1c78ed03041a18f75df104c45405", size = 13283998, upload-time = "2025-12-18T19:29:06.994Z" }, + { url = "https://files.pythonhosted.org/packages/12/84/534a5506f4074e5cc0529e5cd96cfc01bb480e460c7edf5af70d2bcae55e/ruff-0.14.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c70427132db492d25f982fffc8d6c7535cc2fd2c83fc8888f05caaa248521e60", size = 13601891, upload-time = "2025-12-18T19:28:55.811Z" }, + { url = "https://files.pythonhosted.org/packages/0d/1e/14c916087d8598917dbad9b2921d340f7884824ad6e9c55de948a93b106d/ruff-0.14.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5bcf45b681e9f1ee6445d317ce1fa9d6cba9a6049542d1c3d5b5958986be8830", size = 14336660, upload-time = "2025-12-18T19:29:16.531Z" }, + { url = "https://files.pythonhosted.org/packages/f2/1c/d7b67ab43f30013b47c12b42d1acd354c195351a3f7a1d67f59e54227ede/ruff-0.14.10-py3-none-win32.whl", hash = "sha256:104c49fc7ab73f3f3a758039adea978869a918f31b73280db175b43a2d9b51d6", size = 13196187, upload-time = "2025-12-18T19:29:19.006Z" }, + { url = "https://files.pythonhosted.org/packages/fb/9c/896c862e13886fae2af961bef3e6312db9ebc6adc2b156fe95e615dee8c1/ruff-0.14.10-py3-none-win_amd64.whl", hash = "sha256:466297bd73638c6bdf06485683e812db1c00c7ac96d4ddd0294a338c62fdc154", size = 14661283, upload-time = "2025-12-18T19:29:30.16Z" }, + { url = "https://files.pythonhosted.org/packages/74/31/b0e29d572670dca3674eeee78e418f20bdf97fa8aa9ea71380885e175ca0/ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6", size = 13729839, upload-time = "2025-12-18T19:28:48.636Z" }, +] + +[[package]] +name = "s3transfer" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/74/8d69dcb7a9efe8baa2046891735e5dfe433ad558ae23d9e3c14c633d1d58/s3transfer-0.14.0.tar.gz", hash = "sha256:eff12264e7c8b4985074ccce27a3b38a485bb7f7422cc8046fee9be4983e4125", size = 151547, upload-time = "2025-09-09T19:23:31.089Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/f0/ae7ca09223a81a1d890b2557186ea015f6e0502e9b8cb8e1813f1d8cfa4e/s3transfer-0.14.0-py3-none-any.whl", hash = "sha256:ea3b790c7077558ed1f02a3072fb3cb992bbbd253392f4b6e9e8976941c7d456", size = 85712, upload-time = "2025-09-09T19:23:30.041Z" }, +] + +[[package]] +name = "schema" +version = "0.7.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fb/2e/8da627b65577a8f130fe9dfa88ce94fcb24b1f8b59e0fc763ee61abef8b8/schema-0.7.8.tar.gz", hash = "sha256:e86cc08edd6fe6e2522648f4e47e3a31920a76e82cce8937535422e310862ab5", size = 45540, upload-time = "2025-10-11T13:15:40.281Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/75/aad85817266ac5285c93391711d231ca63e9ae7d42cd3ca37549e24ebe52/schema-0.7.8-py2.py3-none-any.whl", hash = "sha256:00bd977fadc7d9521bf289850cd8a8aa5f4948f575476b8daaa5c1b57af2dce1", size = 19108, upload-time = "2025-10-11T17:13:07.323Z" }, +] + +[[package]] +name = "selenium" +version = "4.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "trio" }, + { name = "trio-websocket" }, + { name = "urllib3", extra = ["secure", "socks"] }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/f2/6f584262771d383ad2d21c8b01f8f4af784884f4e25c1f6450265a558a45/selenium-4.1.3-py3-none-any.whl", hash = "sha256:14d28a628c831c105d38305c881c9c7847199bfd728ec84240c5e86fa1c9bd5a", size = 968834, upload-time = "2022-03-09T15:16:43.216Z" }, +] + +[[package]] +name = "setuptools" +version = "80.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, +] + +[[package]] +name = "simplejson" +version = "3.20.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/f4/a1ac5ed32f7ed9a088d62a59d410d4c204b3b3815722e2ccfb491fa8251b/simplejson-3.20.2.tar.gz", hash = "sha256:5fe7a6ce14d1c300d80d08695b7f7e633de6cd72c80644021874d985b3393649", size = 85784, upload-time = "2025-09-26T16:29:36.64Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/9e/f326d43f6bf47f4e7704a4426c36e044c6bedfd24e072fb8e27589a373a5/simplejson-3.20.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90d311ba8fcd733a3677e0be21804827226a57144130ba01c3c6a325e887dd86", size = 93530, upload-time = "2025-09-26T16:28:18.07Z" }, + { url = "https://files.pythonhosted.org/packages/35/28/5a4b8f3483fbfb68f3f460bc002cef3a5735ef30950e7c4adce9c8da15c7/simplejson-3.20.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:feed6806f614bdf7f5cb6d0123cb0c1c5f40407ef103aa935cffaa694e2e0c74", size = 75846, upload-time = "2025-09-26T16:28:19.12Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4d/30dfef83b9ac48afae1cf1ab19c2867e27b8d22b5d9f8ca7ce5a0a157d8c/simplejson-3.20.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6b1d8d7c3e1a205c49e1aee6ba907dcb8ccea83651e6c3e2cb2062f1e52b0726", size = 75661, upload-time = "2025-09-26T16:28:20.219Z" }, + { url = "https://files.pythonhosted.org/packages/09/1d/171009bd35c7099d72ef6afd4bb13527bab469965c968a17d69a203d62a6/simplejson-3.20.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:552f55745044a24c3cb7ec67e54234be56d5d6d0e054f2e4cf4fb3e297429be5", size = 150579, upload-time = "2025-09-26T16:28:21.337Z" }, + { url = "https://files.pythonhosted.org/packages/61/ae/229bbcf90a702adc6bfa476e9f0a37e21d8c58e1059043038797cbe75b8c/simplejson-3.20.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2da97ac65165d66b0570c9e545786f0ac7b5de5854d3711a16cacbcaa8c472d", size = 158797, upload-time = "2025-09-26T16:28:22.53Z" }, + { url = "https://files.pythonhosted.org/packages/90/c5/fefc0ac6b86b9108e302e0af1cf57518f46da0baedd60a12170791d56959/simplejson-3.20.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f59a12966daa356bf68927fca5a67bebac0033cd18b96de9c2d426cd11756cd0", size = 148851, upload-time = "2025-09-26T16:28:23.733Z" }, + { url = "https://files.pythonhosted.org/packages/43/f1/b392952200f3393bb06fbc4dd975fc63a6843261705839355560b7264eb2/simplejson-3.20.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133ae2098a8e162c71da97cdab1f383afdd91373b7ff5fe65169b04167da976b", size = 152598, upload-time = "2025-09-26T16:28:24.962Z" }, + { url = "https://files.pythonhosted.org/packages/f4/b4/d6b7279e52a3e9c0fa8c032ce6164e593e8d9cf390698ee981ed0864291b/simplejson-3.20.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7977640af7b7d5e6a852d26622057d428706a550f7f5083e7c4dd010a84d941f", size = 150498, upload-time = "2025-09-26T16:28:26.114Z" }, + { url = "https://files.pythonhosted.org/packages/62/22/ec2490dd859224326d10c2fac1353e8ad5c84121be4837a6dd6638ba4345/simplejson-3.20.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b530ad6d55e71fa9e93e1109cf8182f427a6355848a4ffa09f69cc44e1512522", size = 152129, upload-time = "2025-09-26T16:28:27.552Z" }, + { url = "https://files.pythonhosted.org/packages/33/ce/b60214d013e93dd9e5a705dcb2b88b6c72bada442a97f79828332217f3eb/simplejson-3.20.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bd96a7d981bf64f0e42345584768da4435c05b24fd3c364663f5fbc8fabf82e3", size = 159359, upload-time = "2025-09-26T16:28:28.667Z" }, + { url = "https://files.pythonhosted.org/packages/99/21/603709455827cdf5b9d83abe726343f542491ca8dc6a2528eb08de0cf034/simplejson-3.20.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f28ee755fadb426ba2e464d6fcf25d3f152a05eb6b38e0b4f790352f5540c769", size = 154717, upload-time = "2025-09-26T16:28:30.288Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f9/dc7f7a4bac16cf7eb55a4df03ad93190e11826d2a8950052949d3dfc11e2/simplejson-3.20.2-cp313-cp313-win32.whl", hash = "sha256:472785b52e48e3eed9b78b95e26a256f59bb1ee38339be3075dad799e2e1e661", size = 74289, upload-time = "2025-09-26T16:28:31.809Z" }, + { url = "https://files.pythonhosted.org/packages/87/10/d42ad61230436735c68af1120622b28a782877146a83d714da7b6a2a1c4e/simplejson-3.20.2-cp313-cp313-win_amd64.whl", hash = "sha256:a1a85013eb33e4820286139540accbe2c98d2da894b2dcefd280209db508e608", size = 75972, upload-time = "2025-09-26T16:28:32.883Z" }, + { url = "https://files.pythonhosted.org/packages/05/5b/83e1ff87eb60ca706972f7e02e15c0b33396e7bdbd080069a5d1b53cf0d8/simplejson-3.20.2-py3-none-any.whl", hash = "sha256:3b6bb7fb96efd673eac2e4235200bfffdc2353ad12c54117e1e4e2fc485ac017", size = 57309, upload-time = "2025-09-26T16:29:35.312Z" }, +] + +[[package]] +name = "six" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041, upload-time = "2021-05-05T14:18:18.379Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053, upload-time = "2021-05-05T14:18:17.237Z" }, +] + +[[package]] +name = "snapshot-restore-py" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/19/2d7584749a7f6d1b4b3a129995b1bc31e70ed9c5ecc323f1ee748b767268/snapshot-restore-py-1.0.0.tar.gz", hash = "sha256:4d27f82fb6f09968f422501e9c3c2dea48a46cd19dc798eb7d6cbc57523c8004", size = 3379, upload-time = "2024-11-13T14:40:22.477Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/b8/f9da2457e9dfb5872042202d69b329940527672e20cbfdb26610c09e1d8e/snapshot_restore_py-1.0.0-py3-none-any.whl", hash = "sha256:38f99e696793790f54658e71c68c7a8a40cea877c81232b5052383b1301aceba", size = 3782, upload-time = "2024-11-13T14:40:21.33Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "snowballstemmer" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, +] + +[[package]] +name = "sphinx" +version = "9.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "roman-numerals" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/50/a8c6ccc36d5eacdfd7913ddccd15a9cee03ecafc5ee2bc40e1f168d85022/sphinx-9.0.4.tar.gz", hash = "sha256:594ef59d042972abbc581d8baa577404abe4e6c3b04ef61bd7fc2acbd51f3fa3", size = 8710502, upload-time = "2025-12-04T07:45:27.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/3f/4bbd76424c393caead2e1eb89777f575dee5c8653e2d4b6afd7a564f5974/sphinx-9.0.4-py3-none-any.whl", hash = "sha256:5bebc595a5e943ea248b99c13814c1c5e10b3ece718976824ffa7959ff95fffb", size = 3917713, upload-time = "2025-12-04T07:45:24.944Z" }, +] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, +] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, +] + +[[package]] +name = "sphinxcontrib-fulltoc" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/d1297db9b75650681e5429e92e13df139ee6b64303ff1b2eea4ebd32c0a9/sphinxcontrib-fulltoc-1.2.0.tar.gz", hash = "sha256:c845d62fc467f3135d4543e9f10e13ef91852683bd1c90fd19d07f9d36757cd9", size = 13752, upload-time = "2017-04-10T14:12:57.75Z" } + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, +] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, +] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, +] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, +] + +[[package]] +name = "sqlalchemy" +version = "1.3.24" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/ab/81bef2f960abf3cdaf32fbf1994f0c6f5e6a5f1667b5713ed6ebf162b6a2/SQLAlchemy-1.3.24.tar.gz", hash = "sha256:ebbb777cbf9312359b897bf81ba00dae0f5cb69fba2a18265dcc18a6f5ef7519", size = 6353598, upload-time = "2021-03-30T23:04:30.273Z" } + +[[package]] +name = "sqlalchemy-utils" +version = "0.36.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, + { name = "sqlalchemy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/85/d8/e889f8071c17773ca0ea3a67a4897ca008e7aff4e5bde0e5b9ef1ee29f1f/SQLAlchemy-Utils-0.36.1.tar.gz", hash = "sha256:4e637c88bf3ac5f99b7d72342092a1f636bea1287b2e3e17d441b0413771f86e", size = 128037, upload-time = "2019-12-23T08:54:53.365Z" } + +[[package]] +name = "sqlparse" +version = "0.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/76/437d71068094df0726366574cf3432a4ed754217b436eb7429415cf2d480/sqlparse-0.5.5.tar.gz", hash = "sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e", size = 120815, upload-time = "2025-12-19T07:17:45.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/4b/359f28a903c13438ef59ebeee215fb25da53066db67b305c125f1c6d2a25/sqlparse-0.5.5-py3-none-any.whl", hash = "sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba", size = 46138, upload-time = "2025-12-19T07:17:46.573Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "stellar" +version = "0.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "humanize" }, + { name = "psutil" }, + { name = "pyyaml" }, + { name = "schema" }, + { name = "sqlalchemy" }, + { name = "sqlalchemy-utils" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/31/091f71810f010241544e9fd0ff794937f86a342693ccbbd542cba205f335/stellar-0.4.5.tar.gz", hash = "sha256:8edd4d19900d47d7e17f1f51dedf7a3cf1e1283d2e52c084b3f69b761f3ae5ce", size = 12083, upload-time = "2018-04-17T07:00:21.203Z" } + +[[package]] +name = "sure" +version = "1.4.11" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mock" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f7/c2/c87b72fbabb9a55bdb71411cdf79113ab857921d178d4dc0d726d836a15a/sure-1.4.11.tar.gz", hash = "sha256:3c8d5271fb18e2c69e2613af1ad400d8df090f1456081635bd3171847303cdaa", size = 45933, upload-time = "2018-05-16T21:40:46.279Z" } + +[[package]] +name = "text-unidecode" +version = "1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ab/e2/e9a00f0ccb71718418230718b3d900e71a5d16e701a3dae079a21e9cd8f8/text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93", size = 76885, upload-time = "2019-08-30T21:36:45.405Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" }, +] + +[[package]] +name = "tomli" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" }, + { url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" }, + { url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/d5/f4/0fbd014909748706c01d16824eadb0307115f9562a15cbb012cd9b3512c5/tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", size = 248586, upload-time = "2025-10-08T22:01:21.164Z" }, + { url = "https://files.pythonhosted.org/packages/30/77/fed85e114bde5e81ecf9bc5da0cc69f2914b38f4708c80ae67d0c10180c5/tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", size = 244792, upload-time = "2025-10-08T22:01:22.417Z" }, + { url = "https://files.pythonhosted.org/packages/55/92/afed3d497f7c186dc71e6ee6d4fcb0acfa5f7d0a1a2878f8beae379ae0cc/tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", size = 248909, upload-time = "2025-10-08T22:01:23.859Z" }, + { url = "https://files.pythonhosted.org/packages/f8/84/ef50c51b5a9472e7265ce1ffc7f24cd4023d289e109f669bdb1553f6a7c2/tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", size = 96946, upload-time = "2025-10-08T22:01:24.893Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b7/718cd1da0884f281f95ccfa3a6cc572d30053cba64603f79d431d3c9b61b/tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", size = 107705, upload-time = "2025-10-08T22:01:26.153Z" }, + { url = "https://files.pythonhosted.org/packages/19/94/aeafa14a52e16163008060506fcb6aa1949d13548d13752171a755c65611/tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", size = 154244, upload-time = "2025-10-08T22:01:27.06Z" }, + { url = "https://files.pythonhosted.org/packages/db/e4/1e58409aa78eefa47ccd19779fc6f36787edbe7d4cd330eeeedb33a4515b/tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", size = 148637, upload-time = "2025-10-08T22:01:28.059Z" }, + { url = "https://files.pythonhosted.org/packages/26/b6/d1eccb62f665e44359226811064596dd6a366ea1f985839c566cd61525ae/tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", size = 241925, upload-time = "2025-10-08T22:01:29.066Z" }, + { url = "https://files.pythonhosted.org/packages/70/91/7cdab9a03e6d3d2bb11beae108da5bdc1c34bdeb06e21163482544ddcc90/tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", size = 249045, upload-time = "2025-10-08T22:01:31.98Z" }, + { url = "https://files.pythonhosted.org/packages/15/1b/8c26874ed1f6e4f1fcfeb868db8a794cbe9f227299402db58cfcc858766c/tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", size = 245835, upload-time = "2025-10-08T22:01:32.989Z" }, + { url = "https://files.pythonhosted.org/packages/fd/42/8e3c6a9a4b1a1360c1a2a39f0b972cef2cc9ebd56025168c4137192a9321/tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", size = 253109, upload-time = "2025-10-08T22:01:34.052Z" }, + { url = "https://files.pythonhosted.org/packages/22/0c/b4da635000a71b5f80130937eeac12e686eefb376b8dee113b4a582bba42/tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", size = 97930, upload-time = "2025-10-08T22:01:35.082Z" }, + { url = "https://files.pythonhosted.org/packages/b9/74/cb1abc870a418ae99cd5c9547d6bce30701a954e0e721821df483ef7223c/tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", size = 107964, upload-time = "2025-10-08T22:01:36.057Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/5c46fff6432a712af9f792944f4fcd7067d8823157949f4e40c56b8b3c83/tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", size = 163065, upload-time = "2025-10-08T22:01:37.27Z" }, + { url = "https://files.pythonhosted.org/packages/39/67/f85d9bd23182f45eca8939cd2bc7050e1f90c41f4a2ecbbd5963a1d1c486/tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", size = 159088, upload-time = "2025-10-08T22:01:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/4b546a0405b9cc0659b399f12b6adb750757baf04250b148d3c5059fc4eb/tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", size = 268193, upload-time = "2025-10-08T22:01:39.712Z" }, + { url = "https://files.pythonhosted.org/packages/42/4f/2c12a72ae22cf7b59a7fe75b3465b7aba40ea9145d026ba41cb382075b0e/tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", size = 275488, upload-time = "2025-10-08T22:01:40.773Z" }, + { url = "https://files.pythonhosted.org/packages/92/04/a038d65dbe160c3aa5a624e93ad98111090f6804027d474ba9c37c8ae186/tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", size = 272669, upload-time = "2025-10-08T22:01:41.824Z" }, + { url = "https://files.pythonhosted.org/packages/be/2f/8b7c60a9d1612a7cbc39ffcca4f21a73bf368a80fc25bccf8253e2563267/tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", size = 279709, upload-time = "2025-10-08T22:01:43.177Z" }, + { url = "https://files.pythonhosted.org/packages/7e/46/cc36c679f09f27ded940281c38607716c86cf8ba4a518d524e349c8b4874/tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", size = 107563, upload-time = "2025-10-08T22:01:44.233Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/426ca8683cf7b753614480484f6437f568fd2fda2edbdf57a2d3d8b27a0b/tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", size = 119756, upload-time = "2025-10-08T22:01:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, +] + +[[package]] +name = "trio" +version = "0.32.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" }, + { name = "idna" }, + { name = "outcome" }, + { name = "sniffio" }, + { name = "sortedcontainers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/ce/0041ddd9160aac0031bcf5ab786c7640d795c797e67c438e15cfedf815c8/trio-0.32.0.tar.gz", hash = "sha256:150f29ec923bcd51231e1d4c71c7006e65247d68759dd1c19af4ea815a25806b", size = 605323, upload-time = "2025-10-31T07:18:17.466Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/bf/945d527ff706233636c73880b22c7c953f3faeb9d6c7e2e85bfbfd0134a0/trio-0.32.0-py3-none-any.whl", hash = "sha256:4ab65984ef8370b79a76659ec87aa3a30c5c7c83ff250b4de88c29a8ab6123c5", size = 512030, upload-time = "2025-10-31T07:18:15.885Z" }, +] + +[[package]] +name = "trio-websocket" +version = "0.12.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "outcome" }, + { name = "trio" }, + { name = "wsproto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/3c/8b4358e81f2f2cfe71b66a267f023a91db20a817b9425dd964873796980a/trio_websocket-0.12.2.tar.gz", hash = "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", size = 33549, upload-time = "2025-02-25T05:16:58.947Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/19/eb640a397bba49ba49ef9dbe2e7e5c04202ba045b6ce2ec36e9cadc51e04/trio_websocket-0.12.2-py3-none-any.whl", hash = "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6", size = 21221, upload-time = "2025-02-25T05:16:57.545Z" }, +] + +[[package]] +name = "trrf" +version = "1.0.0" +source = { editable = "." } +dependencies = [ + { name = "aws-xray-sdk" }, + { name = "awslambdaric" }, + { name = "boto3" }, + { name = "ccg-django-utils" }, + { name = "django" }, + { name = "django-anymail" }, + { name = "django-cache-memoize" }, + { name = "django-countries" }, + { name = "django-csp" }, + { name = "django-extensions" }, + { name = "django-filter" }, + { name = "django-formtools" }, + { name = "django-otp" }, + { name = "django-registration-redux" }, + { name = "django-reversion" }, + { name = "django-simple-history" }, + { name = "django-storages" }, + { name = "django-stronghold" }, + { name = "django-two-factor-auth" }, + { name = "django-user-agents" }, + { name = "djangorestframework" }, + { name = "flatten-json" }, + { name = "gql-query-builder" }, + { name = "graphene-django" }, + { name = "jsonschema" }, + { name = "langcodes" }, + { name = "language-data" }, + { name = "lark" }, + { name = "openapi-client" }, + { name = "openpyxl" }, + { name = "phonenumberslite" }, + { name = "pillow" }, + { name = "psycopg2-binary" }, + { name = "pycountry" }, + { name = "python-dateutil" }, + { name = "python-magic" }, + { name = "pyyaml" }, + { name = "qrcode" }, + { name = "six" }, + { name = "sqlalchemy" }, + { name = "ua-parser" }, + { name = "user-agents" }, + { name = "uwsgi" }, +] + +[package.optional-dependencies] +dev = [ + { name = "django-silk" }, + { name = "ipython" }, + { name = "python-levenshtein" }, + { name = "ruff" }, + { name = "sphinx" }, + { name = "sphinxcontrib-fulltoc" }, + { name = "werkzeug" }, +] +test = [ + { name = "aloe" }, + { name = "aloe-django" }, + { name = "aloe-webdriver" }, + { name = "coverage" }, + { name = "django-nose" }, + { name = "nose-timer" }, + { name = "pynose" }, + { name = "pytest" }, + { name = "pytest-django" }, + { name = "pyvirtualdisplay" }, + { name = "requests" }, + { name = "selenium" }, + { name = "sqlalchemy-utils" }, + { name = "stellar" }, + { name = "sure" }, + { name = "unittest-xml-reporting" }, +] + +[package.metadata] +requires-dist = [ + { name = "aloe", marker = "extra == 'test'", specifier = "==0.2.0" }, + { name = "aloe-django", marker = "extra == 'test'", specifier = "==0.2.0" }, + { name = "aloe-webdriver", marker = "extra == 'test'", specifier = "==0.6.0" }, + { name = "aws-xray-sdk", specifier = "==2.9.0" }, + { name = "awslambdaric", specifier = "==3.1.1" }, + { name = "boto3", specifier = "==1.40.41" }, + { name = "ccg-django-utils", specifier = "==0.4.2" }, + { name = "coverage", marker = "extra == 'test'", specifier = "==5.5" }, + { name = "django", specifier = "==4.2.27" }, + { name = "django-anymail", specifier = "==8.5" }, + { name = "django-cache-memoize", specifier = "==0.1.10" }, + { name = "django-countries", specifier = "==7.2.1" }, + { name = "django-csp", specifier = "==3.7" }, + { name = "django-extensions", specifier = "==3.2.1" }, + { name = "django-filter", specifier = "==21.1" }, + { name = "django-formtools", specifier = "==2.3" }, + { name = "django-nose", marker = "extra == 'test'", specifier = "==1.4.7" }, + { name = "django-otp", specifier = "==1.1.3" }, + { name = "django-registration-redux", specifier = "==2.10" }, + { name = "django-reversion", specifier = "==5.0.0" }, + { name = "django-silk", marker = "extra == 'dev'", specifier = "==4.4.0" }, + { name = "django-simple-history", specifier = "==3.0.0" }, + { name = "django-storages", specifier = "==1.14.6" }, + { name = "django-stronghold", specifier = "==0.4.0" }, + { name = "django-two-factor-auth", specifier = "==1.15.5" }, + { name = "django-user-agents", specifier = "==0.4.0" }, + { name = "djangorestframework", specifier = "==3.15.2" }, + { name = "flatten-json", specifier = "==0.1.13" }, + { name = "gql-query-builder", git = "https://github.com/eresearchqut/gql-query-builder?rev=a983448" }, + { name = "graphene-django", specifier = "==3.1.5" }, + { name = "ipython", marker = "extra == 'dev'" }, + { name = "jsonschema", specifier = "==4.4.0" }, + { name = "langcodes", specifier = "==3.3.0" }, + { name = "language-data", specifier = "==1.3" }, + { name = "lark", specifier = "==1.0.0" }, + { name = "nose-timer", marker = "extra == 'test'", specifier = "==0.7.5" }, + { name = "openapi-client", directory = "clients/xnat/generated" }, + { name = "openpyxl", specifier = "==3.0.9" }, + { name = "phonenumberslite", specifier = "==8.12.39" }, + { name = "pillow", specifier = "==11.3.0" }, + { name = "psycopg2-binary", specifier = "==2.9.10" }, + { name = "pycountry", specifier = "==22.1.10" }, + { name = "pynose", marker = "extra == 'test'", specifier = "==1.5.5" }, + { name = "pytest", marker = "extra == 'test'", specifier = "==7.1.1" }, + { name = "pytest-django", marker = "extra == 'test'", specifier = "==4.5.2" }, + { name = "python-dateutil", specifier = "==2.8.2" }, + { name = "python-levenshtein", marker = "extra == 'dev'" }, + { name = "python-magic", specifier = "==0.4.24" }, + { name = "pyvirtualdisplay", marker = "extra == 'test'", specifier = "==0.2.5" }, + { name = "pyyaml", specifier = "==6.0.3" }, + { name = "qrcode", specifier = "==6.1" }, + { name = "requests", marker = "extra == 'test'", specifier = "==2.32.4" }, + { name = "ruff", marker = "extra == 'dev'" }, + { name = "selenium", marker = "extra == 'test'", specifier = "==4.1.3" }, + { name = "six", specifier = "==1.16.0" }, + { name = "sphinx", marker = "extra == 'dev'" }, + { name = "sphinxcontrib-fulltoc", marker = "extra == 'dev'" }, + { name = "sqlalchemy", specifier = "==1.3.24" }, + { name = "sqlalchemy-utils", marker = "extra == 'test'", specifier = "==0.36.1" }, + { name = "stellar", marker = "extra == 'test'", specifier = "==0.4.5" }, + { name = "sure", marker = "extra == 'test'", specifier = "==1.4.11" }, + { name = "ua-parser", specifier = "==0.10.0" }, + { name = "unittest-xml-reporting", marker = "extra == 'test'", specifier = "==3.2.0" }, + { name = "user-agents", specifier = "==2.2.0" }, + { name = "uwsgi", specifier = "==2.0.30" }, + { name = "werkzeug", marker = "extra == 'dev'", specifier = "==3.1.4" }, +] +provides-extras = ["dev", "test"] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2025.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, +] + +[[package]] +name = "ua-parser" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/68/b5c60fc7386d95de9d66a42b9a9d4898d74de895368964b198003042e297/ua-parser-0.10.0.tar.gz", hash = "sha256:47b1782ed130d890018d983fac37c2a80799d9e0b9c532e734c67cf70f185033", size = 37542, upload-time = "2020-02-27T00:07:10.153Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/22/4d16b08db329fd440eed366d35e4dd7195c9babb4ecac5218f28081522a2/ua_parser-0.10.0-py2.py3-none-any.whl", hash = "sha256:46ab2e383c01dbd2ab284991b87d624a26a08f72da4d7d413f5bfab8b9036f8a", size = 35520, upload-time = "2020-02-27T00:07:08.615Z" }, +] + +[[package]] +name = "unittest-xml-reporting" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lxml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/40/3bf1afc96e93c7322520981ac4593cbb29daa21b48d32746f05ab5563dca/unittest-xml-reporting-3.2.0.tar.gz", hash = "sha256:edd8d3170b40c3a81b8cf910f46c6a304ae2847ec01036d02e9c0f9b85762d28", size = 18002, upload-time = "2022-01-20T19:09:55.76Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/88/f6e9b87428584a3c62cac768185c438ca6d561367a5d267b293259d76075/unittest_xml_reporting-3.2.0-py2.py3-none-any.whl", hash = "sha256:f3d7402e5b3ac72a5ee3149278339db1a8f932ee405f48bcb9c681372f2717d5", size = 20936, upload-time = "2022-01-20T19:09:53.824Z" }, +] + +[[package]] +name = "urllib3" +version = "1.26.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/e8/6ff5e6bc22095cfc59b6ea711b687e2b7ed4bdb373f7eeec370a97d7392f/urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", size = 307380, upload-time = "2024-08-29T15:43:11.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/cf/8435d5a7159e2a9c83a95896ed596f68cf798005fe107cc655b5c5c14704/urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", size = 144225, upload-time = "2024-08-29T15:43:08.921Z" }, +] + +[package.optional-dependencies] +secure = [ + { name = "certifi" }, + { name = "cryptography" }, + { name = "idna" }, + { name = "pyopenssl" }, + { name = "urllib3-secure-extra" }, +] +socks = [ + { name = "pysocks" }, +] + +[[package]] +name = "urllib3-secure-extra" +version = "0.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/67/76b7c055ea787729bb9f839a84689ea2f88e217519d59ae547824431ec95/urllib3-secure-extra-0.1.0.tar.gz", hash = "sha256:ee9409cbfeb4b8609047be4c32fb4317870c602767e53fd8a41005ebe6a41dff", size = 986, upload-time = "2022-08-01T14:51:36.091Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/cd/273b6978ace72ef1d3f35610206e44e4527d557500e3d7b39732f2b4dd3c/urllib3_secure_extra-0.1.0-py2.py3-none-any.whl", hash = "sha256:f7adcb108b4d12a4b26b99eb60e265d087f435052a76aefa396b6ee85e9a6ef9", size = 1444, upload-time = "2022-08-01T14:51:33.853Z" }, +] + +[[package]] +name = "user-agents" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ua-parser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e3/e1/63c5bfb485a945010c8cbc7a52f85573561737648d36b30394248730a7bc/user-agents-2.2.0.tar.gz", hash = "sha256:d36d25178db65308d1458c5fa4ab39c9b2619377010130329f3955e7626ead26", size = 9525, upload-time = "2020-08-23T06:01:56.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/1c/20bb3d7b2bad56d881e3704131ddedbb16eb787101306887dff349064662/user_agents-2.2.0-py3-none-any.whl", hash = "sha256:a98c4dc72ecbc64812c4534108806fb0a0b3a11ec3fd1eafe807cee5b0a942e7", size = 9614, upload-time = "2020-08-23T06:01:54.047Z" }, +] + +[[package]] +name = "uwsgi" +version = "2.0.30" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/f0/d794e9c7359f488b158e88c9e718c5600efdb74a0daf77331e5ffb6c87c4/uwsgi-2.0.30.tar.gz", hash = "sha256:c12aa652124f062ac216077da59f6d247bd7ef938234445881552e58afb1eb5f", size = 822560, upload-time = "2025-06-03T08:13:53.772Z" } + +[[package]] +name = "wcwidth" +version = "0.2.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, +] + +[[package]] +name = "werkzeug" +version = "3.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/45/ea/b0f8eeb287f8df9066e56e831c7824ac6bab645dd6c7a8f4b2d767944f9b/werkzeug-3.1.4.tar.gz", hash = "sha256:cd3cd98b1b92dc3b7b3995038826c68097dcb16f9baa63abe35f20eafeb9fe5e", size = 864687, upload-time = "2025-11-29T02:15:22.841Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl", hash = "sha256:2ad50fb9ed09cc3af22c54698351027ace879a0b60a3b5edf5730b2f7d876905", size = 224960, upload-time = "2025-11-29T02:15:21.13Z" }, +] + +[[package]] +name = "wrapt" +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2a/6de8a50cb435b7f42c46126cf1a54b2aab81784e74c8595c8e025e8f36d3/wrapt-2.0.1.tar.gz", hash = "sha256:9c9c635e78497cacb81e84f8b11b23e0aacac7a136e73b8e5b2109a1d9fc468f", size = 82040, upload-time = "2025-11-07T00:45:33.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/fe/41af4c46b5e498c90fc87981ab2972fbd9f0bccda597adb99d3d3441b94b/wrapt-2.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:47b0f8bafe90f7736151f61482c583c86b0693d80f075a58701dd1549b0010a9", size = 78132, upload-time = "2025-11-07T00:44:04.628Z" }, + { url = "https://files.pythonhosted.org/packages/1c/92/d68895a984a5ebbbfb175512b0c0aad872354a4a2484fbd5552e9f275316/wrapt-2.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cbeb0971e13b4bd81d34169ed57a6dda017328d1a22b62fda45e1d21dd06148f", size = 61211, upload-time = "2025-11-07T00:44:05.626Z" }, + { url = "https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb7cffe572ad0a141a7886a1d2efa5bef0bf7fe021deeea76b3ab334d2c38218", size = 61689, upload-time = "2025-11-07T00:44:06.719Z" }, + { url = "https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c8d60527d1ecfc131426b10d93ab5d53e08a09c5fa0175f6b21b3252080c70a9", size = 121502, upload-time = "2025-11-07T00:44:09.557Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c654eafb01afac55246053d67a4b9a984a3567c3808bb7df2f8de1c1caba2e1c", size = 123110, upload-time = "2025-11-07T00:44:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/e5/08/cdbb965fbe4c02c5233d185d070cabed2ecc1f1e47662854f95d77613f57/wrapt-2.0.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:98d873ed6c8b4ee2418f7afce666751854d6d03e3c0ec2a399bb039cd2ae89db", size = 117434, upload-time = "2025-11-07T00:44:08.138Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d1/6aae2ce39db4cb5216302fa2e9577ad74424dfbe315bd6669725569e048c/wrapt-2.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9e850f5b7fc67af856ff054c71690d54fa940c3ef74209ad9f935b4f66a0233", size = 121533, upload-time = "2025-11-07T00:44:12.142Z" }, + { url = "https://files.pythonhosted.org/packages/79/35/565abf57559fbe0a9155c29879ff43ce8bd28d2ca61033a3a3dd67b70794/wrapt-2.0.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e505629359cb5f751e16e30cf3f91a1d3ddb4552480c205947da415d597f7ac2", size = 116324, upload-time = "2025-11-07T00:44:13.28Z" }, + { url = "https://files.pythonhosted.org/packages/e1/e0/53ff5e76587822ee33e560ad55876d858e384158272cd9947abdd4ad42ca/wrapt-2.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2879af909312d0baf35f08edeea918ee3af7ab57c37fe47cb6a373c9f2749c7b", size = 120627, upload-time = "2025-11-07T00:44:14.431Z" }, + { url = "https://files.pythonhosted.org/packages/7c/7b/38df30fd629fbd7612c407643c63e80e1c60bcc982e30ceeae163a9800e7/wrapt-2.0.1-cp313-cp313-win32.whl", hash = "sha256:d67956c676be5a24102c7407a71f4126d30de2a569a1c7871c9f3cabc94225d7", size = 58252, upload-time = "2025-11-07T00:44:17.814Z" }, + { url = "https://files.pythonhosted.org/packages/85/64/d3954e836ea67c4d3ad5285e5c8fd9d362fd0a189a2db622df457b0f4f6a/wrapt-2.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9ca66b38dd642bf90c59b6738af8070747b610115a39af2498535f62b5cdc1c3", size = 60500, upload-time = "2025-11-07T00:44:15.561Z" }, + { url = "https://files.pythonhosted.org/packages/89/4e/3c8b99ac93527cfab7f116089db120fef16aac96e5f6cdb724ddf286086d/wrapt-2.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:5a4939eae35db6b6cec8e7aa0e833dcca0acad8231672c26c2a9ab7a0f8ac9c8", size = 58993, upload-time = "2025-11-07T00:44:16.65Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f4/eff2b7d711cae20d220780b9300faa05558660afb93f2ff5db61fe725b9a/wrapt-2.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a52f93d95c8d38fed0669da2ebdb0b0376e895d84596a976c15a9eb45e3eccb3", size = 82028, upload-time = "2025-11-07T00:44:18.944Z" }, + { url = "https://files.pythonhosted.org/packages/0c/67/cb945563f66fd0f61a999339460d950f4735c69f18f0a87ca586319b1778/wrapt-2.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e54bbf554ee29fcceee24fa41c4d091398b911da6e7f5d7bffda963c9aed2e1", size = 62949, upload-time = "2025-11-07T00:44:20.074Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ca/f63e177f0bbe1e5cf5e8d9b74a286537cd709724384ff20860f8f6065904/wrapt-2.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:908f8c6c71557f4deaa280f55d0728c3bca0960e8c3dd5ceeeafb3c19942719d", size = 63681, upload-time = "2025-11-07T00:44:21.345Z" }, + { url = "https://files.pythonhosted.org/packages/39/a1/1b88fcd21fd835dca48b556daef750952e917a2794fa20c025489e2e1f0f/wrapt-2.0.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e2f84e9af2060e3904a32cea9bb6db23ce3f91cfd90c6b426757cf7cc01c45c7", size = 152696, upload-time = "2025-11-07T00:44:24.318Z" }, + { url = "https://files.pythonhosted.org/packages/62/1c/d9185500c1960d9f5f77b9c0b890b7fc62282b53af7ad1b6bd779157f714/wrapt-2.0.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3612dc06b436968dfb9142c62e5dfa9eb5924f91120b3c8ff501ad878f90eb3", size = 158859, upload-time = "2025-11-07T00:44:25.494Z" }, + { url = "https://files.pythonhosted.org/packages/91/60/5d796ed0f481ec003220c7878a1d6894652efe089853a208ea0838c13086/wrapt-2.0.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6d2d947d266d99a1477cd005b23cbd09465276e302515e122df56bb9511aca1b", size = 146068, upload-time = "2025-11-07T00:44:22.81Z" }, + { url = "https://files.pythonhosted.org/packages/04/f8/75282dd72f102ddbfba137e1e15ecba47b40acff32c08ae97edbf53f469e/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7d539241e87b650cbc4c3ac9f32c8d1ac8a54e510f6dca3f6ab60dcfd48c9b10", size = 155724, upload-time = "2025-11-07T00:44:26.634Z" }, + { url = "https://files.pythonhosted.org/packages/5a/27/fe39c51d1b344caebb4a6a9372157bdb8d25b194b3561b52c8ffc40ac7d1/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4811e15d88ee62dbf5c77f2c3ff3932b1e3ac92323ba3912f51fc4016ce81ecf", size = 144413, upload-time = "2025-11-07T00:44:27.939Z" }, + { url = "https://files.pythonhosted.org/packages/83/2b/9f6b643fe39d4505c7bf926d7c2595b7cb4b607c8c6b500e56c6b36ac238/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c1c91405fcf1d501fa5d55df21e58ea49e6b879ae829f1039faaf7e5e509b41e", size = 150325, upload-time = "2025-11-07T00:44:29.29Z" }, + { url = "https://files.pythonhosted.org/packages/bb/b6/20ffcf2558596a7f58a2e69c89597128781f0b88e124bf5a4cadc05b8139/wrapt-2.0.1-cp313-cp313t-win32.whl", hash = "sha256:e76e3f91f864e89db8b8d2a8311d57df93f01ad6bb1e9b9976d1f2e83e18315c", size = 59943, upload-time = "2025-11-07T00:44:33.211Z" }, + { url = "https://files.pythonhosted.org/packages/87/6a/0e56111cbb3320151eed5d3821ee1373be13e05b376ea0870711f18810c3/wrapt-2.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:83ce30937f0ba0d28818807b303a412440c4b63e39d3d8fc036a94764b728c92", size = 63240, upload-time = "2025-11-07T00:44:30.935Z" }, + { url = "https://files.pythonhosted.org/packages/1d/54/5ab4c53ea1f7f7e5c3e7c1095db92932cc32fd62359d285486d00c2884c3/wrapt-2.0.1-cp313-cp313t-win_arm64.whl", hash = "sha256:4b55cacc57e1dc2d0991dbe74c6419ffd415fb66474a02335cb10efd1aa3f84f", size = 60416, upload-time = "2025-11-07T00:44:32.002Z" }, + { url = "https://files.pythonhosted.org/packages/73/81/d08d83c102709258e7730d3cd25befd114c60e43ef3891d7e6877971c514/wrapt-2.0.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:5e53b428f65ece6d9dad23cb87e64506392b720a0b45076c05354d27a13351a1", size = 78290, upload-time = "2025-11-07T00:44:34.691Z" }, + { url = "https://files.pythonhosted.org/packages/f6/14/393afba2abb65677f313aa680ff0981e829626fed39b6a7e3ec807487790/wrapt-2.0.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ad3ee9d0f254851c71780966eb417ef8e72117155cff04821ab9b60549694a55", size = 61255, upload-time = "2025-11-07T00:44:35.762Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/a4a1f2fba205a9462e36e708ba37e5ac95f4987a0f1f8fd23f0bf1fc3b0f/wrapt-2.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7b822c61ed04ee6ad64bc90d13368ad6eb094db54883b5dde2182f67a7f22c0", size = 61797, upload-time = "2025-11-07T00:44:37.22Z" }, + { url = "https://files.pythonhosted.org/packages/12/db/99ba5c37cf1c4fad35349174f1e38bd8d992340afc1ff27f526729b98986/wrapt-2.0.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7164a55f5e83a9a0b031d3ffab4d4e36bbec42e7025db560f225489fa929e509", size = 120470, upload-time = "2025-11-07T00:44:39.425Z" }, + { url = "https://files.pythonhosted.org/packages/30/3f/a1c8d2411eb826d695fc3395a431757331582907a0ec59afce8fe8712473/wrapt-2.0.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e60690ba71a57424c8d9ff28f8d006b7ad7772c22a4af432188572cd7fa004a1", size = 122851, upload-time = "2025-11-07T00:44:40.582Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8d/72c74a63f201768d6a04a8845c7976f86be6f5ff4d74996c272cefc8dafc/wrapt-2.0.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3cd1a4bd9a7a619922a8557e1318232e7269b5fb69d4ba97b04d20450a6bf970", size = 117433, upload-time = "2025-11-07T00:44:38.313Z" }, + { url = "https://files.pythonhosted.org/packages/c7/5a/df37cf4042cb13b08256f8e27023e2f9b3d471d553376616591bb99bcb31/wrapt-2.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b4c2e3d777e38e913b8ce3a6257af72fb608f86a1df471cb1d4339755d0a807c", size = 121280, upload-time = "2025-11-07T00:44:41.69Z" }, + { url = "https://files.pythonhosted.org/packages/54/34/40d6bc89349f9931e1186ceb3e5fbd61d307fef814f09fbbac98ada6a0c8/wrapt-2.0.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3d366aa598d69416b5afedf1faa539fac40c1d80a42f6b236c88c73a3c8f2d41", size = 116343, upload-time = "2025-11-07T00:44:43.013Z" }, + { url = "https://files.pythonhosted.org/packages/70/66/81c3461adece09d20781dee17c2366fdf0cb8754738b521d221ca056d596/wrapt-2.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c235095d6d090aa903f1db61f892fffb779c1eaeb2a50e566b52001f7a0f66ed", size = 119650, upload-time = "2025-11-07T00:44:44.523Z" }, + { url = "https://files.pythonhosted.org/packages/46/3a/d0146db8be8761a9e388cc9cc1c312b36d583950ec91696f19bbbb44af5a/wrapt-2.0.1-cp314-cp314-win32.whl", hash = "sha256:bfb5539005259f8127ea9c885bdc231978c06b7a980e63a8a61c8c4c979719d0", size = 58701, upload-time = "2025-11-07T00:44:48.277Z" }, + { url = "https://files.pythonhosted.org/packages/1a/38/5359da9af7d64554be63e9046164bd4d8ff289a2dd365677d25ba3342c08/wrapt-2.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:4ae879acc449caa9ed43fc36ba08392b9412ee67941748d31d94e3cedb36628c", size = 60947, upload-time = "2025-11-07T00:44:46.086Z" }, + { url = "https://files.pythonhosted.org/packages/aa/3f/96db0619276a833842bf36343685fa04f987dd6e3037f314531a1e00492b/wrapt-2.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:8639b843c9efd84675f1e100ed9e99538ebea7297b62c4b45a7042edb84db03e", size = 59359, upload-time = "2025-11-07T00:44:47.164Z" }, + { url = "https://files.pythonhosted.org/packages/71/49/5f5d1e867bf2064bf3933bc6cf36ade23505f3902390e175e392173d36a2/wrapt-2.0.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:9219a1d946a9b32bb23ccae66bdb61e35c62773ce7ca6509ceea70f344656b7b", size = 82031, upload-time = "2025-11-07T00:44:49.4Z" }, + { url = "https://files.pythonhosted.org/packages/2b/89/0009a218d88db66ceb83921e5685e820e2c61b59bbbb1324ba65342668bc/wrapt-2.0.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fa4184e74197af3adad3c889a1af95b53bb0466bced92ea99a0c014e48323eec", size = 62952, upload-time = "2025-11-07T00:44:50.74Z" }, + { url = "https://files.pythonhosted.org/packages/ae/18/9b968e920dd05d6e44bcc918a046d02afea0fb31b2f1c80ee4020f377cbe/wrapt-2.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c5ef2f2b8a53b7caee2f797ef166a390fef73979b15778a4a153e4b5fedce8fa", size = 63688, upload-time = "2025-11-07T00:44:52.248Z" }, + { url = "https://files.pythonhosted.org/packages/a6/7d/78bdcb75826725885d9ea26c49a03071b10c4c92da93edda612910f150e4/wrapt-2.0.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e042d653a4745be832d5aa190ff80ee4f02c34b21f4b785745eceacd0907b815", size = 152706, upload-time = "2025-11-07T00:44:54.613Z" }, + { url = "https://files.pythonhosted.org/packages/dd/77/cac1d46f47d32084a703df0d2d29d47e7eb2a7d19fa5cbca0e529ef57659/wrapt-2.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2afa23318136709c4b23d87d543b425c399887b4057936cd20386d5b1422b6fa", size = 158866, upload-time = "2025-11-07T00:44:55.79Z" }, + { url = "https://files.pythonhosted.org/packages/8a/11/b521406daa2421508903bf8d5e8b929216ec2af04839db31c0a2c525eee0/wrapt-2.0.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6c72328f668cf4c503ffcf9434c2b71fdd624345ced7941bc6693e61bbe36bef", size = 146148, upload-time = "2025-11-07T00:44:53.388Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c0/340b272bed297baa7c9ce0c98ef7017d9c035a17a6a71dce3184b8382da2/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3793ac154afb0e5b45d1233cb94d354ef7a983708cc3bb12563853b1d8d53747", size = 155737, upload-time = "2025-11-07T00:44:56.971Z" }, + { url = "https://files.pythonhosted.org/packages/f3/93/bfcb1fb2bdf186e9c2883a4d1ab45ab099c79cbf8f4e70ea453811fa3ea7/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:fec0d993ecba3991645b4857837277469c8cc4c554a7e24d064d1ca291cfb81f", size = 144451, upload-time = "2025-11-07T00:44:58.515Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6b/dca504fb18d971139d232652656180e3bd57120e1193d9a5899c3c0b7cdd/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:949520bccc1fa227274da7d03bf238be15389cd94e32e4297b92337df9b7a349", size = 150353, upload-time = "2025-11-07T00:44:59.753Z" }, + { url = "https://files.pythonhosted.org/packages/1d/f6/a1de4bd3653afdf91d250ca5c721ee51195df2b61a4603d4b373aa804d1d/wrapt-2.0.1-cp314-cp314t-win32.whl", hash = "sha256:be9e84e91d6497ba62594158d3d31ec0486c60055c49179edc51ee43d095f79c", size = 60609, upload-time = "2025-11-07T00:45:03.315Z" }, + { url = "https://files.pythonhosted.org/packages/01/3a/07cd60a9d26fe73efead61c7830af975dfdba8537632d410462672e4432b/wrapt-2.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:61c4956171c7434634401db448371277d07032a81cc21c599c22953374781395", size = 64038, upload-time = "2025-11-07T00:45:00.948Z" }, + { url = "https://files.pythonhosted.org/packages/41/99/8a06b8e17dddbf321325ae4eb12465804120f699cd1b8a355718300c62da/wrapt-2.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:35cdbd478607036fee40273be8ed54a451f5f23121bd9d4be515158f9498f7ad", size = 60634, upload-time = "2025-11-07T00:45:02.087Z" }, + { url = "https://files.pythonhosted.org/packages/15/d1/b51471c11592ff9c012bd3e2f7334a6ff2f42a7aed2caffcf0bdddc9cb89/wrapt-2.0.1-py3-none-any.whl", hash = "sha256:4d2ce1bf1a48c5277d7969259232b57645aae5686dba1eaeade39442277afbca", size = 44046, upload-time = "2025-11-07T00:45:32.116Z" }, +] + +[[package]] +name = "wsproto" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/79/12135bdf8b9c9367b8701c2c19a14c913c120b882d50b014ca0d38083c2c/wsproto-1.3.2.tar.gz", hash = "sha256:b86885dcf294e15204919950f666e06ffc6c7c114ca900b060d6e16293528294", size = 50116, upload-time = "2025-11-20T18:18:01.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl", hash = "sha256:61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584", size = 24405, upload-time = "2025-11-20T18:18:00.454Z" }, +] From bd961dacd8ccfe90e90fe7e27c2b7e4dc2b93b92 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 14:12:24 +1000 Subject: [PATCH 02/34] Upgrade to Django 5 --- pyproject.toml | 28 ++++++------ uv.lock | 121 ++++++++++++++++++++++++++----------------------- 2 files changed, 79 insertions(+), 70 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 80d1efc6a..6b8f8cdd9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,13 +10,13 @@ authors = [{ name = "Queensland University of Technology - eResearch" }] requires-python = ">=3.13" dependencies = [ "ccg-django-utils==0.4.2", - "Django==4.2.27", - "django-anymail==8.5", - "django-countries==7.2.1", - "django-csp==3.7", - "django-extensions==3.2.1", - "django-registration-redux==2.10", - "djangorestframework==3.15.2", + "Django==5.2.1", + "django-anymail==14.0", + "django-countries==7.6.1", + "django-csp==3.8", + "django-extensions==3.2.3", + "django-registration-redux==2.13", + "djangorestframework==3.16.0", "django-storages==1.14.6", "django-stronghold==0.4.0", "jsonschema==4.4.0", @@ -29,22 +29,22 @@ dependencies = [ "six==1.16.0", "SQLAlchemy==1.3.24", "uwsgi==2.0.30", - "django-formtools==2.3", - "django-otp==1.1.3", - "django-two-factor-auth==1.15.5", + "django-formtools==2.5.1", + "django-otp==1.6.3", + "django-two-factor-auth==1.18.0", "phonenumberslite==8.12.39", "Pillow==11.3.0", "qrcode==6.1", - "django-reversion==5.0.0", + "django-reversion==6.1.0", "ua-parser==0.10.0", "user-agents==2.2.0", "django-user-agents==0.4.0", - "django-simple-history==3.0.0", + "django-simple-history==3.11.0", "lark==1.0.0", "boto3==1.40.41", "aws-xray-sdk==2.9.0", - "graphene-django==3.1.5", - "django-filter==21.1", + "graphene-django==3.2.3", + "django-filter==25.1", "flatten_json==0.1.13", "gql-query-builder @ git+https://github.com/eresearchqut/gql-query-builder@a983448", "awslambdaric==3.1.1", diff --git a/uv.lock b/uv.lock index e3f804b5b..dcc99e7a5 100644 --- a/uv.lock +++ b/uv.lock @@ -393,29 +393,31 @@ wheels = [ [[package]] name = "django" -version = "4.2.27" +version = "5.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asgiref" }, { name = "sqlparse" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/ff/6aa5a94b85837af893ca82227301ac6ddf4798afda86151fb2066d26ca0a/django-4.2.27.tar.gz", hash = "sha256:b865fbe0f4a3d1ee36594c5efa42b20db3c8bbb10dff0736face1c6e4bda5b92", size = 10432781, upload-time = "2025-12-02T14:01:49.006Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/10/0d546258772b8f31398e67c85e52c66ebc2b13a647193c3eef8ee433f1a8/django-5.2.1.tar.gz", hash = "sha256:57fe1f1b59462caed092c80b3dd324fd92161b620d59a9ba9181c34746c97284", size = 10818735, upload-time = "2025-05-07T14:06:17.543Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/f5/1a2319cc090870bfe8c62ef5ad881a6b73b5f4ce7330c5cf2cb4f9536b12/django-4.2.27-py3-none-any.whl", hash = "sha256:f393a394053713e7d213984555c5b7d3caeee78b2ccb729888a0774dff6c11a8", size = 7995090, upload-time = "2025-12-02T14:01:44.234Z" }, + { url = "https://files.pythonhosted.org/packages/90/92/7448697b5838b3a1c6e1d2d6a673e908d0398e84dc4f803a2ce11e7ffc0f/django-5.2.1-py3-none-any.whl", hash = "sha256:a9b680e84f9a0e71da83e399f1e922e1ab37b2173ced046b541c72e1589a5961", size = 8301833, upload-time = "2025-05-07T14:06:10.955Z" }, ] [[package]] name = "django-anymail" -version = "8.5" +version = "14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, + { name = "idna" }, { name = "requests" }, + { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/c0/30cb9cb0a597bbac68d3a7c7a4e078974e83b575c04a4c186729bb74b676/django-anymail-8.5.tar.gz", hash = "sha256:677e937dc9e2671ca7631abb1d94ddc6b840beb3d53c0fbf699e866a6a9ba92f", size = 80667, upload-time = "2022-01-19T23:12:37.287Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/cb/25aa288f7ce37331d0ebe0321f3a3079add297b037d6d4b4b363bf080e0b/django_anymail-14.0.tar.gz", hash = "sha256:ca42e52da62d2c96ce92412f9d68ef6d2067d96a384096b6e932d6a247e9fd61", size = 106257, upload-time = "2025-12-18T01:36:07.944Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/4e/a784d0b72ddd54e3b4739ab0c5c8972989bded5086ba185f401bc68c51b4/django_anymail-8.5-py3-none-any.whl", hash = "sha256:2325932f56f914d96e0a54db850f2b246ed2277b753f75319620d051a51551e2", size = 100275, upload-time = "2022-01-19T23:12:35.729Z" }, + { url = "https://files.pythonhosted.org/packages/81/83/6d92a06dba4ef471aa1bbbe2e1461103800beea6a4bf95ac5f3d0f21e167/django_anymail-14.0-py3-none-any.whl", hash = "sha256:98e5575bcff231952a92117b7d0a4dd37fab582333a343de302d415a31dc72b1", size = 146119, upload-time = "2025-12-18T01:36:06.612Z" }, ] [[package]] @@ -429,59 +431,63 @@ wheels = [ [[package]] name = "django-countries" -version = "7.2.1" +version = "7.6.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ec/26/9bdf4384ee75e9056f3eabf9e8dbbbc7681612043dc1365a327b46e4edb8/django-countries-7.2.1.tar.gz", hash = "sha256:26878b54d36bedff30b4535ceefcb8af6784741a8b30b1b8a662fb14a936a4ab", size = 649955, upload-time = "2021-05-11T10:54:31.443Z" } +dependencies = [ + { name = "asgiref" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/c3/ddb94bb50455ae80ff90ddb5affcc28f7e7a48f9c9852cf8bb8fe712fec0/django-countries-7.6.1.tar.gz", hash = "sha256:c772d4e3e54afcc5f97a018544e96f246c6d9f1db51898ab0c15cd57e19437cf", size = 675623, upload-time = "2024-04-01T21:01:09.414Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/b3/e9148a3f8394b090dc961eb97ae549e22d8185645a6b3e8c31d5f6932d45/django_countries-7.2.1-py3-none-any.whl", hash = "sha256:adc965f1d348124274b7d918fc1aad5e29609758af999e1822baa9f2cc06d1b8", size = 825377, upload-time = "2021-05-11T10:54:27.155Z" }, + { url = "https://files.pythonhosted.org/packages/7e/46/b6931858e5161e5d9166bfcfde3af0b7d60ba89e4f7dd8f033e591c68794/django_countries-7.6.1-py3-none-any.whl", hash = "sha256:1ed20842fe0f6194f91faca21076649513846a8787c9eb5aeec3cbe1656b8acc", size = 864507, upload-time = "2024-04-01T21:01:05.702Z" }, ] [[package]] name = "django-csp" -version = "3.7" +version = "3.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/76/bdb879b0e73798a8f5d568d19e77995c0319b82ddfa6c2fee4d15e956e1a/django_csp-3.7.tar.gz", hash = "sha256:01eda02ad3f10261c74131cdc0b5a6a62b7c7ad4fd017fbefb7a14776e0a9727", size = 12821, upload-time = "2020-08-12T18:50:35.687Z" } +sdist = { url = "https://files.pythonhosted.org/packages/68/16/c3c65ad59997284402e54d00797c7aca96572df911aede3e1f2cc2e029f8/django_csp-3.8.tar.gz", hash = "sha256:ef0f1a9f7d8da68ae6e169c02e9ac661c0ecf04db70e0d1d85640512a68471c0", size = 13341, upload-time = "2024-03-01T14:00:30.013Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/04/1e3b703e584fef3522065415d9b2f7550d8996d7e590d9b70b8c480ecc69/django_csp-3.7-py2.py3-none-any.whl", hash = "sha256:01443a07723f9a479d498bd7bb63571aaa771e690f64bde515db6cdb76e8041a", size = 17390, upload-time = "2020-08-12T18:50:34.713Z" }, + { url = "https://files.pythonhosted.org/packages/14/ff/2c7a4b6706125a17bd0071802e4894c28772cfcdea20a086a2be3c5fafda/django_csp-3.8-py3-none-any.whl", hash = "sha256:19b2978b03fcd73517d7d67acbc04fbbcaec0facc3e83baa502965892d1e0719", size = 17410, upload-time = "2024-03-01T14:00:28.135Z" }, ] [[package]] name = "django-extensions" -version = "3.2.1" +version = "3.2.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/aa/94ea07a87d52f484a562e701ee7af8dee4a43f3260b10d500d178ecbfcc7/django-extensions-3.2.1.tar.gz", hash = "sha256:2a4f4d757be2563cd1ff7cfdf2e57468f5f931cc88b23cf82ca75717aae504a4", size = 624971, upload-time = "2022-09-09T11:09:51.853Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/f1/318684c9466968bf9a9c221663128206e460c1a67f595055be4b284cde8a/django-extensions-3.2.3.tar.gz", hash = "sha256:44d27919d04e23b3f40231c4ab7af4e61ce832ef46d610cc650d53e68328410a", size = 277216, upload-time = "2023-06-05T17:09:01.447Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/a8/36d25c69589a44680e49f8b1886f65379829af4464384bd10a205c93532a/django_extensions-3.2.1-py3-none-any.whl", hash = "sha256:421464be390289513f86cb5e18eb43e5dc1de8b4c27ba9faa3b91261b0d67e09", size = 229444, upload-time = "2022-09-09T11:09:47.085Z" }, + { url = "https://files.pythonhosted.org/packages/a7/7e/ba12b9660642663f5273141018d2bec0a1cae1711f4f6d1093920e157946/django_extensions-3.2.3-py3-none-any.whl", hash = "sha256:9600b7562f79a92cbf1fde6403c04fee314608fefbb595502e34383ae8203401", size = 229868, upload-time = "2023-06-05T17:08:58.197Z" }, ] [[package]] name = "django-filter" -version = "21.1" +version = "25.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e3/90/819a74f0c9650a7ceda158d85a6010b4ce3d4e215e0c69ec9f3a733ce72f/django-filter-21.1.tar.gz", hash = "sha256:632a251fa8f1aadb4b8cceff932bb52fe2f826dd7dfe7f3eac40e5c463d6836e", size = 154188, upload-time = "2021-09-24T14:08:38.813Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/40/c702a6fe8cccac9bf426b55724ebdf57d10a132bae80a17691d0cf0b9bac/django_filter-25.1.tar.gz", hash = "sha256:1ec9eef48fa8da1c0ac9b411744b16c3f4c31176c867886e4c48da369c407153", size = 143021, upload-time = "2025-02-14T16:30:53.238Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/90/8fbf530e14dbcaf502cd80078cbae9e4f805f20888973488ebe8480c3c28/django_filter-21.1-py3-none-any.whl", hash = "sha256:f4a6737a30104c98d2e2a5fb93043f36dd7978e0c7ddc92f5998e85433ea5063", size = 81384, upload-time = "2021-09-24T14:08:37.152Z" }, + { url = "https://files.pythonhosted.org/packages/07/a6/70dcd68537c434ba7cb9277d403c5c829caf04f35baf5eb9458be251e382/django_filter-25.1-py3-none-any.whl", hash = "sha256:4fa48677cf5857b9b1347fed23e355ea792464e0fe07244d1fdfb8a806215b80", size = 94114, upload-time = "2025-02-14T16:30:50.435Z" }, ] [[package]] name = "django-formtools" -version = "2.3" +version = "2.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6e/b0/41ca0a8b7f2ce073f4cfca6adcc7b502a4a894fad9b80505b2ad13dc7aac/django-formtools-2.3.tar.gz", hash = "sha256:9663b6eca64777b68d6d4142efad8597fe9a685924673b25aa8a1dcff4db00c3", size = 83706, upload-time = "2021-04-19T03:58:47.452Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f8/bb9b228fc33230186f3612a6fc96274a81bab3509817498f2632d7aa6367/django-formtools-2.5.1.tar.gz", hash = "sha256:47cb34552c6efca088863d693284d04fc36eaaf350eb21e1a1d935e0df523c93", size = 88637, upload-time = "2023-12-19T10:30:59.78Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8e/dd/0bce8b9cc6dfa80a4c510e625f54be4348e799d9c594f98c1cd83e63cd2a/django_formtools-2.3-py3-none-any.whl", hash = "sha256:4699937e19ee041d803943714fe0c1c7ad4cab802600eb64bbf4cdd0a1bfe7d9", size = 148867, upload-time = "2021-04-19T03:58:32.131Z" }, + { url = "https://files.pythonhosted.org/packages/12/63/91a107e3aaaf3987bad036494dfd8cc2675f4a66d22e65ffd6711f84ba70/django_formtools-2.5.1-py3-none-any.whl", hash = "sha256:bce9b64eda52cc1eef6961cc649cf75aacd1a707c2fff08d6c3efcbc8e7e761a", size = 170651, upload-time = "2023-12-19T10:30:02.816Z" }, ] [[package]] @@ -498,14 +504,14 @@ wheels = [ [[package]] name = "django-otp" -version = "1.1.3" +version = "1.6.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b7/16/774bcfca894416f9f34867b75e60f7282830db140b109916061f77a9c611/django-otp-1.1.3.tar.gz", hash = "sha256:f002c71d4ea7f514590be00492980d3c87397b73dc20542e1c4fc00b66f2dda1", size = 61330, upload-time = "2021-11-30T18:11:31.727Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/83/ec6bf6b2b142e394c3dcbf7e9641ad5976c8b36947fba060dc71017a904d/django_otp-1.6.3.tar.gz", hash = "sha256:93f0011bc4cb6ef278733d75de351f3e2de6fd13ece56cf27b63e1da42322d24", size = 74641, upload-time = "2025-10-25T15:36:16.272Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/a2/d0a4587be38d9c5a2981b45ba6386f5b05fa6309a5fe93f8917dc15b1b85/django_otp-1.1.3-py3-none-any.whl", hash = "sha256:8637be826c0465d0fd1710e4472efe9fc83883853a2141fefdbace9358d20003", size = 61438, upload-time = "2021-11-30T18:11:30.252Z" }, + { url = "https://files.pythonhosted.org/packages/77/23/22d8b4e9280351d6236fac1fa30b5f1fc8fff70c4b615ba9d78f20468b5f/django_otp-1.6.3-py3-none-any.whl", hash = "sha256:f7ff9e6980c4aa9e6b9f7a7477de0a65583891a78e5b8c6cae0ec7cc0f78ce55", size = 68346, upload-time = "2025-10-25T15:36:14.748Z" }, ] [[package]] @@ -522,23 +528,23 @@ wheels = [ [[package]] name = "django-registration-redux" -version = "2.10" +version = "2.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/99/03/12bbb6262b26716c2df5b187bc321b6bd226d30b5ca60b080d641f079e9a/django-registration-redux-2.10.tar.gz", hash = "sha256:de25c3ae04ec466edc8a41e03d7ff817fdb996ffd00333550b9c4b960593fdff", size = 115983, upload-time = "2022-03-09T02:20:24.132Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/47/960fb3f88d0080a94fffb6fc98ff986012d3a968c030036cf79abdd40242/django-registration-redux-2.13.tar.gz", hash = "sha256:9793a05b32b1d7342c6ef3e0140b2951b7dbde058b3ba6e8a232b534928279f9", size = 125883, upload-time = "2023-10-27T02:41:46.863Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/74/f4/6aae205d40dfe3fe57e9ba6b288def0c360bcb803b046c992ab494bdb8b4/django_registration_redux-2.10-py2.py3-none-any.whl", hash = "sha256:ef6817b300f56f82658058d6e060eef819ae882074721e8e98870ed195a24118", size = 213227, upload-time = "2022-03-09T02:20:21.883Z" }, + { url = "https://files.pythonhosted.org/packages/32/7f/715af6a1322a1bc8fc84befa469a048dd5983eeac49f464ffa01bff33f00/django_registration_redux-2.13-py2.py3-none-any.whl", hash = "sha256:547c86ad9b951cf743075b5486f304e51e450b45d04e5ef04392838a9cff3da8", size = 218441, upload-time = "2023-10-27T02:41:44.565Z" }, ] [[package]] name = "django-reversion" -version = "5.0.0" +version = "6.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5f/5c/9cb8596a9ade29bd849f0ac46b8287cfd9e031751dbcbfafc2294d475e8c/django-reversion-5.0.0.tar.gz", hash = "sha256:0bade3c399387451087f0c67835e0d3d186d767de6a5c5ba53a88eafc3f271c8", size = 71748, upload-time = "2022-02-20T16:49:44.05Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9b/8b/72000ad3ba05cb72134f62ad093267e3d83d8fdf1406102d2a1a2ec7d55e/django_reversion-6.1.0.tar.gz", hash = "sha256:31dd7fee02e2a21af7c2d0a61c1c0f27ba07df2317c9a0a3f31d3ee40069025d", size = 76140, upload-time = "2025-12-12T20:23:51.948Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/0e/ad4a20275bd5ddcbd6fadcf64b5a6732471086dd611da1619c57e1b69391/django_reversion-5.0.0-py3-none-any.whl", hash = "sha256:7bea725de7f56769d89a5a712cf7b7f1b02abc27655432f2eb1a703264986d99", size = 86917, upload-time = "2022-02-20T16:49:42.198Z" }, + { url = "https://files.pythonhosted.org/packages/5e/8e/c80904ce5cb94f78cdd7d794cb7b4a8e8891a7515621bbce5f2a45de6555/django_reversion-6.1.0-py3-none-any.whl", hash = "sha256:1f5815791d9accdb0bad9d5982668f217dc65225be57041ae9641dbdcd838ce3", size = 86196, upload-time = "2025-12-12T20:23:50.18Z" }, ] [[package]] @@ -562,11 +568,14 @@ wheels = [ [[package]] name = "django-simple-history" -version = "3.0.0" +version = "3.11.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/d4/6fb7ff5410a7737bcb0be782b2af1958c13a9c5a0429a4f41a0a72d8214d/django-simple-history-3.0.0.tar.gz", hash = "sha256:66fe76c560054be393c52b1799661e104fbe372918d37d151e5d41c676158118", size = 533193, upload-time = "2021-04-19T15:02:28.15Z" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/11/410049f1454b99a78f719d3403fc89437c2a38ee092e939d5ab8d4846738/django_simple_history-3.11.0.tar.gz", hash = "sha256:2c587479cf2c3071e9aa555d0d11b73676994db4910770958f57659ade2deffe", size = 234862, upload-time = "2025-12-11T13:50:55.022Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/5b/dbab8270380803077f6bc80941388dbb6c4d242628e0bae932943f686273/django_simple_history-3.0.0-py2.py3-none-any.whl", hash = "sha256:a312adfe8fbec4c450b08e641b11249a8a589a7e7d1ba2404764b8b5bed53552", size = 84847, upload-time = "2021-04-19T15:02:41.425Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c2/e9854a3438cfc80891ab4d3826b7c61a0fe5ba3a4da89104a8f5c9afb5df/django_simple_history-3.11.0-py3-none-any.whl", hash = "sha256:f3c298db49e418ffce7fb709a5e83108452ea2179ec5c4b9232484c25427192a", size = 81868, upload-time = "2025-12-11T13:50:53.71Z" }, ] [[package]] @@ -591,7 +600,7 @@ wheels = [ [[package]] name = "django-two-factor-auth" -version = "1.15.5" +version = "1.18.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, @@ -600,9 +609,9 @@ dependencies = [ { name = "django-phonenumber-field" }, { name = "qrcode" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3c/64/dd90e403226707a54dd710ea87d28596e8a3f9c1310cd6ea038c4d12e9ff/django-two-factor-auth-1.15.5.tar.gz", hash = "sha256:87510ccdbf6053ba80aa217367fa122ff4cecd04c0afb8becbb2c96655057616", size = 158421, upload-time = "2023-09-22T07:19:32.985Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/06/3d352dd4fe8c5a75f0de7fec413a81bf641e629ef113d5f7508003ec3a87/django_two_factor_auth-1.18.0.tar.gz", hash = "sha256:9307a38d7102981662f762f282966da6db76953c9f89d9d25a629993d545f517", size = 170380, upload-time = "2025-09-16T15:38:58.748Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/f3/235ce3894bde12a99778f8278f236ea1638c1e2d32103491637ce2ded775/django_two_factor_auth-1.15.5-py3-none-any.whl", hash = "sha256:42fc95a250380a123faec301d350eab588c165af83d5c38840c1cc13f3aac746", size = 290755, upload-time = "2023-09-22T07:20:10.283Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0d/4ed2309acf33ff0ad161b947cd182532250f30390c19ce029f7da7ddbc62/django_two_factor_auth-1.18.0-py3-none-any.whl", hash = "sha256:3c1a6ece0bf9c72026457b2a66322b382d41ccdace4c328cf536f19f2ba60f3e", size = 301704, upload-time = "2025-09-16T15:38:56.954Z" }, ] [[package]] @@ -620,14 +629,14 @@ wheels = [ [[package]] name = "djangorestframework" -version = "3.15.2" +version = "3.16.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2c/ce/31482eb688bdb4e271027076199e1aa8d02507e530b6d272ab8b4481557c/djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad", size = 1067420, upload-time = "2024-06-19T07:59:32.891Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/97/112c5a72e6917949b6d8a18ad6c6e72c46da4290c8f36ee5f1c1dcbc9901/djangorestframework-3.16.0.tar.gz", hash = "sha256:f022ff46613584de994c0c6a4aebbace5fd700555fbe9d33b865ebf173eba6c9", size = 1068408, upload-time = "2025-03-28T14:18:42.065Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/b6/fa99d8f05eff3a9310286ae84c4059b08c301ae4ab33ae32e46e8ef76491/djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20", size = 1071235, upload-time = "2024-06-19T07:59:26.106Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3e/2448e93f4f87fc9a9f35e73e3c05669e0edd0c2526834686e949bb1fd303/djangorestframework-3.16.0-py3-none-any.whl", hash = "sha256:bea7e9f6b96a8584c5224bfb2e4348dfb3f8b5e34edbecb98da258e892089361", size = 1067305, upload-time = "2025-03-28T14:18:39.489Z" }, ] [[package]] @@ -724,7 +733,7 @@ wheels = [ [[package]] name = "graphene-django" -version = "3.1.5" +version = "3.2.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, @@ -734,9 +743,9 @@ dependencies = [ { name = "promise" }, { name = "text-unidecode" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/23/70/1b1d29d817eadc88cbbee2a049e5a1f6924f96cddbeec6c303660a3005b4/graphene-django-3.1.5.tar.gz", hash = "sha256:abe42f820b9731d94bebff6d73088d0dc2ffb8c8863a6d7bf3d378412d866a3b", size = 84744, upload-time = "2023-08-09T22:13:22.002Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/7a/8aef131349329dcd167578720f6364412f1728bfda14bba22c1e7b5d8365/graphene-django-3.2.3.tar.gz", hash = "sha256:d831bfe8e9a6e77e477b7854faef4addb318f386119a69ee4c57b74560f3e07d", size = 88393, upload-time = "2025-03-13T08:33:03.949Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/4e/5f3306f1664a4c3d77f21545914c866a66c419fdba1f43a62930a2ae57e7/graphene_django-3.1.5-py2.py3-none-any.whl", hash = "sha256:2e42742fae21fa50e514f3acae26a9bc6cb5e51c179a97b3db5390ff258ca816", size = 110165, upload-time = "2023-08-09T22:13:20.766Z" }, + { url = "https://files.pythonhosted.org/packages/18/35/ab9c668222f6271a0b71efb147c46816229dbb9fa5d15ee6b025eb08d4b2/graphene_django-3.2.3-py2.py3-none-any.whl", hash = "sha256:0c673a4dad315b26b4d18eb379ad0c7027fd6a36d23a1848b7c7c09a14a9271e", size = 114959, upload-time = "2025-03-13T08:33:02.453Z" }, ] [[package]] @@ -2213,28 +2222,28 @@ requires-dist = [ { name = "boto3", specifier = "==1.40.41" }, { name = "ccg-django-utils", specifier = "==0.4.2" }, { name = "coverage", marker = "extra == 'test'", specifier = "==5.5" }, - { name = "django", specifier = "==4.2.27" }, - { name = "django-anymail", specifier = "==8.5" }, + { name = "django", specifier = "==5.2.1" }, + { name = "django-anymail", specifier = "==14.0" }, { name = "django-cache-memoize", specifier = "==0.1.10" }, - { name = "django-countries", specifier = "==7.2.1" }, - { name = "django-csp", specifier = "==3.7" }, - { name = "django-extensions", specifier = "==3.2.1" }, - { name = "django-filter", specifier = "==21.1" }, - { name = "django-formtools", specifier = "==2.3" }, + { name = "django-countries", specifier = "==7.6.1" }, + { name = "django-csp", specifier = "==3.8" }, + { name = "django-extensions", specifier = "==3.2.3" }, + { name = "django-filter", specifier = "==25.1" }, + { name = "django-formtools", specifier = "==2.5.1" }, { name = "django-nose", marker = "extra == 'test'", specifier = "==1.4.7" }, - { name = "django-otp", specifier = "==1.1.3" }, - { name = "django-registration-redux", specifier = "==2.10" }, - { name = "django-reversion", specifier = "==5.0.0" }, + { name = "django-otp", specifier = "==1.6.3" }, + { name = "django-registration-redux", specifier = "==2.13" }, + { name = "django-reversion", specifier = "==6.1.0" }, { name = "django-silk", marker = "extra == 'dev'", specifier = "==4.4.0" }, - { name = "django-simple-history", specifier = "==3.0.0" }, + { name = "django-simple-history", specifier = "==3.11.0" }, { name = "django-storages", specifier = "==1.14.6" }, { name = "django-stronghold", specifier = "==0.4.0" }, - { name = "django-two-factor-auth", specifier = "==1.15.5" }, + { name = "django-two-factor-auth", specifier = "==1.18.0" }, { name = "django-user-agents", specifier = "==0.4.0" }, - { name = "djangorestframework", specifier = "==3.15.2" }, + { name = "djangorestframework", specifier = "==3.16.0" }, { name = "flatten-json", specifier = "==0.1.13" }, { name = "gql-query-builder", git = "https://github.com/eresearchqut/gql-query-builder?rev=a983448" }, - { name = "graphene-django", specifier = "==3.1.5" }, + { name = "graphene-django", specifier = "==3.2.3" }, { name = "ipython", marker = "extra == 'dev'" }, { name = "jsonschema", specifier = "==4.4.0" }, { name = "langcodes", specifier = "==3.3.0" }, From cdaa4100b165ebcbddd018eb88ed89dad8459d7a Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 14:13:25 +1000 Subject: [PATCH 03/34] Use new method_decrator decorator --- rdrf/rdrf/auth/views.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rdrf/rdrf/auth/views.py b/rdrf/rdrf/auth/views.py index bae89cd68..23c25f132 100644 --- a/rdrf/rdrf/auth/views.py +++ b/rdrf/rdrf/auth/views.py @@ -6,6 +6,7 @@ from django.dispatch import receiver from django.shortcuts import redirect from django.urls import reverse +from django.utils.decorators import method_decorator from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ from django.views.decorators.cache import never_cache @@ -25,8 +26,8 @@ logger = logging.getLogger(__name__) -@tfv.utils.class_view_decorator(sensitive_post_parameters()) -@tfv.utils.class_view_decorator(never_cache) +@method_decorator(sensitive_post_parameters(), name="dispatch") +@method_decorator(never_cache, name="dispatch") class LoginView(tfv.LoginView): form_list = ( ("auth", LoginAuthenticationForm), @@ -79,17 +80,17 @@ def user_login_callback(sender, request=None, user=None, **kwargs): # Customised Two Factor views -@tfv.utils.class_view_decorator(never_cache) +@method_decorator(never_cache, name="dispatch") class QRGeneratorView(tfv.core.QRGeneratorView): session_key_name = "two_fact_auth_key" -@tfv.utils.class_view_decorator(never_cache) +@method_decorator(never_cache, name="dispatch") class SetupView(tfv.core.SetupView): session_key_name = "two_fact_auth_key" -@tfv.utils.class_view_decorator(never_cache) +@method_decorator(never_cache, name="dispatch") class DisableView(tfv.profile.DisableView): def form_valid(self, form): user = self.request.user From c536613f4fc598e0beefa8301151e7d7e3fa63d1 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 14:14:25 +1000 Subject: [PATCH 04/34] Use new STORAGES setting --- rdrf/rdrf/settings.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/rdrf/rdrf/settings.py b/rdrf/rdrf/settings.py index 7183eee6c..40fde3c3f 100644 --- a/rdrf/rdrf/settings.py +++ b/rdrf/rdrf/settings.py @@ -312,9 +312,23 @@ # Use S3 by default to avoid writing sensitive data to FS in production if env.get("FILE_STORAGE", "S3") == "FS": - DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage" + STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + }, + } else: - DEFAULT_FILE_STORAGE = "rdrf.db.filestorage.CustomS3Storage" + STORAGES = { + "default": { + "BACKEND": "rdrf.db.filestorage.CustomS3Storage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + }, + } # Configure different aspects of file uploads to S3 From d842bd784bfca11c7038fcee8248df9eb220813f Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 15:16:53 +1000 Subject: [PATCH 05/34] Update deprecated selenium selectors --- .../testing/behaviour/features/auth/steps.py | 12 ++--- .../features/longitudinal_followups/steps.py | 2 +- .../features/longitudinal_followups/utils.py | 5 +- rdrf/rdrf/testing/behaviour/features/steps.py | 52 +++++++++---------- rdrf/rdrf/testing/behaviour/features/utils.py | 2 +- 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/rdrf/rdrf/testing/behaviour/features/auth/steps.py b/rdrf/rdrf/testing/behaviour/features/auth/steps.py index 863443568..6d7c255e9 100644 --- a/rdrf/rdrf/testing/behaviour/features/auth/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/auth/steps.py @@ -81,12 +81,12 @@ def patient_self_registration(_step, client_name, email_address, password): # Populate plain text fields for key, value in params.items(): - world.browser.find_element_by_id(key).send_keys(value + Keys.TAB) + world.browser.find_element(By.ID, key).send_keys(value + Keys.TAB) # Select the gender radio button # 1 - Male, 2 - Female, 3 - Indeterminate - world.browser.find_element_by_css_selector( - "input[name='gender'][value='1']" + world.browser.find_element( + By.CSS_SELECTOR, "input[name='gender'][value='1']" ).click() captcha_iframe_element = world.browser.find_element( @@ -96,7 +96,7 @@ def patient_self_registration(_step, client_name, email_address, password): world.browser.switch_to.frame(captcha_iframe_element) scroll_to_y(500) - world.browser.find_element_by_id("recaptcha-anchor").send_keys(Keys.SPACE) + world.browser.find_element(By.ID, "recaptcha-anchor").send_keys(Keys.SPACE) world.browser.switch_to.default_content() @@ -191,8 +191,8 @@ def open_option_from_menu(_step, option, menu): @step('"([^"]+)" image is displayed') def assert_is_image_displayed(_step, image_alt): - image = world.browser.find_element_by_css_selector( - f'img[alt="{image_alt}"]' + image = world.browser.find_element( + By.CSS_SELECTOR, f'img[alt="{image_alt}"]' ) assert_true(image.is_displayed()) diff --git a/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/steps.py b/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/steps.py index f97856a77..945b06d2d 100644 --- a/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/steps.py @@ -71,7 +71,7 @@ def empty_mail(_step): def check_mail(_step, count): go_to_url("mail/outbox") sent_emails = len( - world.browser.find_elements_by_css_selector(EMAIL_SELECTOR) + world.browser.find_elements(By.CSS_SELECTOR, EMAIL_SELECTOR) ) assert_equal(sent_emails, int(count)) diff --git a/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/utils.py b/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/utils.py index 9ba7ca622..0644b45b0 100644 --- a/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/utils.py +++ b/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/utils.py @@ -1,4 +1,5 @@ from aloe import world +from selenium.webdriver.common.by import By from rdrf.testing.behaviour.features.utils import wait_for_first_section @@ -6,8 +7,8 @@ def get_email(n): - return world.browser.find_elements_by_css_selector( - f"{EMAIL_SELECTOR}:nth-child({n}) > td a" + return world.browser.find_elements( + By.CSS_SELECTOR, f"{EMAIL_SELECTOR}:nth-child({n}) > td a" ) diff --git a/rdrf/rdrf/testing/behaviour/features/steps.py b/rdrf/rdrf/testing/behaviour/features/steps.py index e3ac36b6a..b7c74912f 100644 --- a/rdrf/rdrf/testing/behaviour/features/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/steps.py @@ -32,7 +32,7 @@ def login_as_angelman_user(step, user_name): @step('I should be at the welcome page and see a message which says "([^"]+)"') def angelman_user_logged_in(step, welcome_message): - login_message = world.browser.find_element_by_tag_name("h4").text + login_message = world.browser.find_element(By.TAG_NAME, "h4").text # Ensure that the user sees the expected page after successfully logging in assert world.expected_login_message in login_message @@ -43,7 +43,7 @@ def try_to_manually_activate_new_user(step): world.browser.get( world.site_url + "admin/registration/registrationprofile/" ) - world.browser.find_element_by_id("action-toggle").send_keys(Keys.SPACE) + world.browser.find_element(By.ID, "action-toggle").send_keys(Keys.SPACE) world.browser.find_element( by=By.XPATH, @@ -58,8 +58,9 @@ def try_to_manually_activate_new_user(step): def check_user_activated(step): # Ensure that the user has been successfully activated by checking for the green tick icon assert not ( - world.browser.find_elements_by_css_selector( - 'img[src$="/static/admin/img/icon-yes.svg"].ng-hide' + world.browser.find_elements( + By.CSS_SELECTOR, + 'img[src$="/static/admin/img/icon-yes.svg"].ng-hide', ) ) @@ -132,7 +133,7 @@ def click_patient_listing(step, patient_name): @step('I click on "(.*)" in "(.*)" group in sidebar') def click_sidebar_group_item(step, item_name, group_name): # E.g. And I click "Clinical Data" in "Main" group in sidebar - sidebar = world.browser.find_element_by_id("sidebar") + sidebar = world.browser.find_element(By.ID, "sidebar") form_group_panel = sidebar.find_element( by=By.XPATH, value='//div[@class="card-header"][contains(., "%s")]' % group_name, @@ -145,7 +146,7 @@ def click_sidebar_group_item(step, item_name, group_name): @step('I press "(.*)" button in "(.*)" group in sidebar') def click_button_sidebar_group(step, button_name, group_name): - sidebar = world.browser.find_element_by_id("sidebar") + sidebar = world.browser.find_element(By.ID, "sidebar") form_group_panel = sidebar.find_element( by=By.XPATH, value='//div[@class="card-header"][contains(., "%s")]' % group_name, @@ -163,7 +164,7 @@ def enter_cde_on_form(step, cde_value, form, section, cde): utils.wait_for_first_section() - form_block = world.browser.find_element_by_id("main-form") + form_block = world.browser.find_element(By.ID, "main-form") section_div_heading = form_block.find_element( by=By.XPATH, value=".//div[@class='card-header'][contains(., '%s')]" % section, @@ -207,7 +208,7 @@ def correct_item(input_element): utils.wait_for_first_section() - form_block = world.browser.find_element_by_id("main-form") + form_block = world.browser.find_element(By.ID, "main-form") section_div_heading = form_block.find_element( by=By.XPATH, value=".//div[@class='card-header'][contains(., '%s')]" % section, @@ -265,7 +266,7 @@ def error_message_is(step, error_message): @step('location is "(.*)"') def location_is(step, location_name): - sidebar = world.browser.find_element_by_id("sidebar") + sidebar = world.browser.find_element(By.ID, "sidebar") location_parts = location_name.split("/") if len(location_parts) == 1: sidebar.find_element( @@ -295,7 +296,7 @@ def click_module_dropdown_in_patient_listing(step, module_name, patient_name): else: button_caption, form_name = "Modules", module_name - patients_table = world.browser.find_element_by_id("patients_table") + patients_table = world.browser.find_element(By.ID, "patients_table") patient_row = patients_table.find_element( by=By.XPATH, @@ -315,13 +316,13 @@ def click_module_dropdown_in_patient_listing(step, module_name, patient_name): @step("press the navigate back button") def press_back_button(step): - button = world.browser.find_element_by_css_selector("a.previous-form") + button = world.browser.find_element(By.CSS_SELECTOR, "a.previous-form") utils.click(button) @step("press the navigate forward button") def press_forward_button(step): - button = world.browser.find_element_by_css_selector("a.next-form") + button = world.browser.find_element(By.CSS_SELECTOR, "a.next-form") utils.click(button) @@ -398,7 +399,7 @@ def value_is(step, textfield_label, expected_value): def value_is2(step, section, cde, expected_value): utils.wait_for_first_section() - form_block = world.browser.find_element_by_id("main-form") + form_block = world.browser.find_element(By.ID, "main-form") section_div_heading = form_block.find_element( by=By.XPATH, value=".//div[@class='card-header'][contains(., '%s')]" % section, @@ -431,7 +432,7 @@ def check_checkbox(step, checkbox_label): @step("Sign consent") def sign_consent(step): - signature_div = world.browser.find_element_by_id("signature") + signature_div = world.browser.find_element(By.ID, "signature") utils.click(signature_div) @@ -474,7 +475,7 @@ def goto_patient(step): @step('the page header should be "(.*)"') def the_page_header_should_be(step, header): - sidebar = world.browser.find_element_by_id("sidebar") + sidebar = world.browser.find_element(By.ID, "sidebar") panel_body = sidebar.find_element( by=By.XPATH, value='//div[@class="card-body"]' ) @@ -495,7 +496,7 @@ def login_as_role(step, role): @step('log in as "(.*)" with "(.*)" password') def login_as_user(step, username, password): - utils.click(world.browser.find_element_by_link_text("Log in")) + utils.click(world.browser.find_element(By.LINK_TEXT, "Log in")) username_field = world.browser.find_element( by=By.XPATH, value='.//input[@name="auth-username"]' ) @@ -537,8 +538,8 @@ def click_user_menu(step): @step('the progress indicator should be "(.*)"') def the_progress_indicator_should_be(step, percentage): - progress_bar = world.browser.find_element_by_css_selector( - ".progress .progress-bar" + progress_bar = world.browser.find_element( + By.CSS_SELECTOR, ".progress .progress-bar" ) logger.info(progress_bar.text.strip()) @@ -556,7 +557,7 @@ def go_home(step): def go_to_registry(step, name): world.browser.get(world.site_url) utils.click( - world.browser.find_element_by_link_text("Registries on this site") + world.browser.find_element(By.LINK_TEXT, "Registries on this site") ) utils.click(world.browser.find_element(by=By.PARTIAL_LINK_TEXT, value=name)) @@ -583,7 +584,7 @@ def accept_alert(step): @step('When I click "(.*)" in sidebar') def sidebar_click(step, sidebar_link_text): - utils.click(world.browser.find_element_by_link_text(sidebar_link_text)) + utils.click(world.browser.find_element(By.LINK_TEXT, sidebar_link_text)) @step("I click Cancel") @@ -661,8 +662,8 @@ def should_be_able_to_download(step, download_name): import re link_pattern = re.compile(r".*\/uploads\/\d+$") - download_link_element = world.browser.find_element_by_link_text( - download_name + download_link_element = world.browser.find_element( + By.LINK_TEXT, download_name ) if not download_link_element: raise Exception("Could not locate download link %s" % download_name) @@ -698,7 +699,7 @@ def check_history_popup(step, form, section, cde, history_values_csv): from selenium.webdriver.support.ui import WebDriverWait history_values = history_values_csv.split(",") - form_block = world.browser.find_element_by_id("main-form") + form_block = world.browser.find_element(By.ID, "main-form") section_div_heading = form_block.find_element( by=By.XPATH, value=".//div[@class='card-header'][contains(., '%s')]" % section, @@ -742,12 +743,11 @@ def find_cell(historical_value): @step('check the clear checkbox for multisection "(.*)" cde "(.*)" file "(.*)"') def clear_file_upload(step, section, cde, download_name): - from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as ec from selenium.webdriver.support.ui import WebDriverWait - download_link_element = world.browser.find_element_by_link_text( - download_name + download_link_element = world.browser.find_element( + By.LINK_TEXT, download_name ) clear_checkbox_path = ".//following-sibling::input[@type='checkbox']" WebDriverWait(world.browser, TEST_WAIT).until( diff --git a/rdrf/rdrf/testing/behaviour/features/utils.py b/rdrf/rdrf/testing/behaviour/features/utils.py index 7b96e5006..504faedfe 100644 --- a/rdrf/rdrf/testing/behaviour/features/utils.py +++ b/rdrf/rdrf/testing/behaviour/features/utils.py @@ -344,7 +344,7 @@ def scroll_to_cde(section, cde, item=None): if "__prefix__" in input_id: # hack to avoid this error input_id = input_id.replace("__prefix__", "0") - input_element = world.browser.find_element_by_id(input_id) + input_element = world.browser.find_element(By.ID, input_id) if not input_element: raise Exception("could not locate input with id %s" % input_id) From 610ca62a982319b9c0b60044f36d9f53a6bdb2f8 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 16:04:43 +1000 Subject: [PATCH 06/34] Use non-naive timezone-aware times now that USE_TZ=true is the default --- rdrf/rdrf/db/dynamic_data.py | 7 ++++--- rdrf/rdrf/db/generalised_field_expressions.py | 6 +++--- rdrf/rdrf/exporter_utils.py | 6 +++--- rdrf/rdrf/forms/progress/form_progress.py | 6 ++++-- rdrf/rdrf/management/commands/check_logins.py | 5 +++-- .../create_longitudinal_followup_entries.py | 5 ++--- .../commands/send_longitudinal_followups.py | 5 +++-- rdrf/rdrf/models/workflow_models.py | 4 ++-- .../content/export_import/main_exporters.py | 5 +++-- rdrf/rdrf/services/io/defs/exporter.py | 4 ++-- .../notifications/longitudinal_followups.py | 7 ++++--- .../services/io/notifications/reminders.py | 5 +++-- .../features/longitudinal_followups/steps.py | 5 +++-- .../unit/longitudinal_followup_tests.py | 21 ++++++++++--------- rdrf/rdrf/testing/unit/tests.py | 9 ++++---- rdrf/rdrf/users/views.py | 8 ++++--- rdrf/rdrf/views/mailbox_view.py | 8 +++++-- rdrf/registry/patients/admin.py | 6 +++--- rdrf/registry/patients/models.py | 18 +++++++--------- rdrf/useraudit/models.py | 6 +++--- rdrf/useraudit/tests/utils.py | 6 +++--- 21 files changed, 83 insertions(+), 69 deletions(-) diff --git a/rdrf/rdrf/db/dynamic_data.py b/rdrf/rdrf/db/dynamic_data.py index ddd820c25..f1f130159 100644 --- a/rdrf/rdrf/db/dynamic_data.py +++ b/rdrf/rdrf/db/dynamic_data.py @@ -5,6 +5,7 @@ from aws_xray_sdk.core import xray_recorder from django.core.files.uploadedfile import InMemoryUploadedFile +from django.utils import timezone from rdrf.db.filestorage import create_filestorage from rdrf.forms.file_upload import FileUpload, wrap_fs_data_for_form @@ -246,7 +247,7 @@ def __init__( self.django_model = None def update_timestamps(self, form_model): - t = datetime.datetime.now() + t = timezone.now() form_timestamp = form_model.name + "_timestamp" self.global_timestamp = t self.form_timestamps[form_timestamp] = t @@ -893,7 +894,7 @@ def save_dynamic_data( else: record = self._get_record(registry.code, collection_name).first() - form_data["timestamp"] = datetime.datetime.now() + form_data["timestamp"] = timezone.now() if self.current_form_model: form_timestamp_key = "%s_timestamp" % self.current_form_model.name @@ -940,7 +941,7 @@ def _save_longitudinal_snapshot( self, registry_code, record, form_name=None, form_user=None ): try: - timestamp = str(datetime.datetime.now()) + timestamp = str(timezone.now()) patient_id = record.data["django_id"] snapshot = { "django_id": patient_id, diff --git a/rdrf/rdrf/db/generalised_field_expressions.py b/rdrf/rdrf/db/generalised_field_expressions.py index 63677d802..615aaaea8 100644 --- a/rdrf/rdrf/db/generalised_field_expressions.py +++ b/rdrf/rdrf/db/generalised_field_expressions.py @@ -565,7 +565,7 @@ def evaluate(self, patient_model, mongo_record): ) def set_value(self, patient_model, mongo_record, new_value, **kwargs): - from datetime import datetime + from django.utils import timezone from rdrf.db.contexts_api import RDRFContextManager @@ -587,7 +587,7 @@ def set_value(self, patient_model, mongo_record, new_value, **kwargs): } form_timestamp_key = "%s_timestamp" % self.form_model.name - form_timestamp_value = datetime.now() + form_timestamp_value = timezone.now() form_dict = { "name": self.form_model.name, @@ -638,7 +638,7 @@ def set_value(self, patient_model, mongo_record, new_value, **kwargs): form_dict["sections"].append(section_dict) if not form_exists: form_timestamp_key = "%s_timestamp" - form_timestamp_value = datetime.now() + form_timestamp_value = timezone.now() form_dict = { "name": self.form_model.name, "sections": [ diff --git a/rdrf/rdrf/exporter_utils.py b/rdrf/rdrf/exporter_utils.py index 5970cdd55..1cc038283 100644 --- a/rdrf/rdrf/exporter_utils.py +++ b/rdrf/rdrf/exporter_utils.py @@ -1,10 +1,10 @@ import io import logging import zipfile -from datetime import datetime from functools import reduce from django.http import HttpResponse +from django.utils import timezone from rdrf.services.io.defs.exporter import Exporter, ExportType @@ -19,7 +19,7 @@ def write_export_single_file(yaml_data, registry, export_type): if yaml_data is None: return - export_time = str(datetime.now()) + export_time = str(timezone.now()) yaml_export_filename = f"export_{export_time}_{registry.name}{partial_descriptor_str(export_type)}.yaml" @@ -49,7 +49,7 @@ def write_export_zip(exports, export_type): response = HttpResponse( zip_stream.getvalue(), content_type="application/zip" ) - export_time = str(datetime.now()) + export_time = str(timezone.now()) name = ( "export_" + export_time diff --git a/rdrf/rdrf/forms/progress/form_progress.py b/rdrf/rdrf/forms/progress/form_progress.py index 961810734..31cf48cef 100644 --- a/rdrf/rdrf/forms/progress/form_progress.py +++ b/rdrf/rdrf/forms/progress/form_progress.py @@ -201,10 +201,12 @@ def _calculate_form_progress(self): return result def _calculate_form_currency(self): - from datetime import datetime, timedelta + from datetime import timedelta + + from django.utils import timezone form_timestamp_key = "%s_timestamp" % self.form_model.name - one_year_ago = datetime.now() - timedelta(weeks=52) + one_year_ago = timezone.now() - timedelta(weeks=52) if self.dynamic_data is None: return False diff --git a/rdrf/rdrf/management/commands/check_logins.py b/rdrf/rdrf/management/commands/check_logins.py index 9780ef8e8..1d1c4c97c 100644 --- a/rdrf/rdrf/management/commands/check_logins.py +++ b/rdrf/rdrf/management/commands/check_logins.py @@ -1,7 +1,8 @@ import sys -from datetime import datetime, timedelta +from datetime import timedelta from django.core.management import BaseCommand +from django.utils import timezone from registry.groups.models import CustomUser from rdrf.models.definition.models import Registry @@ -86,7 +87,7 @@ def _get_numdays(self, registry_model): return 365 def _get_threshold(self, num_days): - return datetime.now() - timedelta(days=num_days) + return timezone.now() - timedelta(days=num_days) def handle(self, *args, **options): action = options.get("action") diff --git a/rdrf/rdrf/management/commands/create_longitudinal_followup_entries.py b/rdrf/rdrf/management/commands/create_longitudinal_followup_entries.py index 7df8bd682..5472e8520 100644 --- a/rdrf/rdrf/management/commands/create_longitudinal_followup_entries.py +++ b/rdrf/rdrf/management/commands/create_longitudinal_followup_entries.py @@ -1,6 +1,5 @@ -from datetime import datetime - from django.core.management.base import BaseCommand, CommandError +from django.utils import timezone from registry.patients.models import ( LivingStates, LongitudinalFollowupEntry, @@ -71,7 +70,7 @@ def handle(self, *args, **options): self.style.SUCCESS(f"Found {len(pending_entries)} pending entries") ) - now = datetime.now() + now = timezone.now() patients = Patient.objects.filter(rdrf_registry=registry) def can_add(patient): diff --git a/rdrf/rdrf/management/commands/send_longitudinal_followups.py b/rdrf/rdrf/management/commands/send_longitudinal_followups.py index ee95062e3..07852ef42 100644 --- a/rdrf/rdrf/management/commands/send_longitudinal_followups.py +++ b/rdrf/rdrf/management/commands/send_longitudinal_followups.py @@ -1,6 +1,7 @@ -from datetime import datetime, timedelta +from datetime import timedelta from django.core.management import BaseCommand +from django.utils import timezone from rdrf.services.io.notifications.longitudinal_followups import ( send_longitudinal_followups, @@ -16,5 +17,5 @@ def add_arguments(self, parser): def handle(self, *args, **options): delta_seconds = options["delta_seconds"] - now = datetime.now() + now = timezone.now() send_longitudinal_followups(now + timedelta(seconds=delta_seconds)) diff --git a/rdrf/rdrf/models/workflow_models.py b/rdrf/rdrf/models/workflow_models.py index b52931554..f452bc25d 100644 --- a/rdrf/rdrf/models/workflow_models.py +++ b/rdrf/rdrf/models/workflow_models.py @@ -1,8 +1,8 @@ import logging -from datetime import datetime from django.db import models from django.urls import reverse +from django.utils import timezone from registry.groups.models import CustomUser from rdrf.events.events import EventType @@ -43,7 +43,7 @@ class ClinicianSignupRequest(models.Model): def send_request(self): self._send_email() self.state = "emailed" - self.emailed_date = datetime.now() + self.emailed_date = timezone.now() self.save() def notify_participant_on_verification(self, diagnosis=""): diff --git a/rdrf/rdrf/services/io/content/export_import/main_exporters.py b/rdrf/rdrf/services/io/content/export_import/main_exporters.py index 30429f137..c1c38738a 100644 --- a/rdrf/rdrf/services/io/content/export_import/main_exporters.py +++ b/rdrf/rdrf/services/io/content/export_import/main_exporters.py @@ -4,7 +4,8 @@ import shutil import tempfile from collections import OrderedDict -from datetime import datetime + +from django.utils import timezone from rdrf.models.definition.models import Registry @@ -63,7 +64,7 @@ def export(self, filename=None, verbose=False, indented_logs=True): ) if exporter.export(**self.export_context): self.meta.append(exporter.get_meta_info(top_level=True)) - self.exported_at = datetime.now() + self.exported_at = timezone.now() self.write_out_meta_info() diff --git a/rdrf/rdrf/services/io/defs/exporter.py b/rdrf/rdrf/services/io/defs/exporter.py index cd09d99c1..e81fb6b48 100644 --- a/rdrf/rdrf/services/io/defs/exporter.py +++ b/rdrf/rdrf/services/io/defs/exporter.py @@ -1,4 +1,3 @@ -import datetime import json import logging from decimal import Decimal @@ -8,6 +7,7 @@ from django.contrib.auth.models import Group from django.core.exceptions import ValidationError from django.forms.models import model_to_dict +from django.utils import timezone from registry.patients.models import ( NextOfKinRelationship, PatientStage, @@ -332,7 +332,7 @@ def _skeleton_export(self, export_type): data["RDRF_VERSION"] = VERSION data["EXPORT_TYPE"] = export_type - data["EXPORT_TIME"] = str(datetime.datetime.now()) + data["EXPORT_TIME"] = str(timezone.now()) data["REGISTRY_VERSION"] = self._get_registry_version() if self.registry: diff --git a/rdrf/rdrf/services/io/notifications/longitudinal_followups.py b/rdrf/rdrf/services/io/notifications/longitudinal_followups.py index f601ef1f8..e1d741957 100644 --- a/rdrf/rdrf/services/io/notifications/longitudinal_followups.py +++ b/rdrf/rdrf/services/io/notifications/longitudinal_followups.py @@ -13,6 +13,7 @@ ) from django.db.models.functions import Coalesce from django.urls import reverse +from django.utils import timezone from registry.patients.models import ( ConsentValue, LongitudinalFollowupEntry, @@ -40,7 +41,7 @@ def handle_longitudinal_followups(user, patient, registry, context_form_group): if context_form_group is None: return - now = datetime.datetime.now() + now = timezone.now() new_entries = [ LongitudinalFollowupEntry( longitudinal_followup=longitudinal_followup, @@ -147,7 +148,7 @@ def _serialize_entries(patient_entries): def with_now(func): def wrapper(now=None): - return func(now=now or datetime.datetime.now()) + return func(now=now or timezone.now()) return wrapper @@ -237,7 +238,7 @@ def send_longitudinal_followups(now): if not any(entry.send_at <= now for entry in patient_entries): continue - sent_at = datetime.datetime.now() + sent_at = timezone.now() longitudinal_followups = _serialize_entries(patient_entries) diff --git a/rdrf/rdrf/services/io/notifications/reminders.py b/rdrf/rdrf/services/io/notifications/reminders.py index 47bcc2a43..0a68d3eb8 100644 --- a/rdrf/rdrf/services/io/notifications/reminders.py +++ b/rdrf/rdrf/services/io/notifications/reminders.py @@ -1,6 +1,7 @@ import json import logging -from datetime import datetime + +from django.utils import timezone from rdrf.services.io.notifications.email_notification import ( EmailNotificationHistory, @@ -21,7 +22,7 @@ def __init__(self, user, registry_model, process_func=process_notification): def _can_send(self): # These are the rules for MTM - should we push into config? - now = datetime.now() + now = timezone.now() existing_reminders = self._get_reminders() num_sent = len(existing_reminders) if num_sent >= 2: diff --git a/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/steps.py b/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/steps.py index 945b06d2d..3b3e4bcb1 100644 --- a/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/longitudinal_followups/steps.py @@ -1,6 +1,7 @@ -from datetime import datetime, timedelta +from datetime import timedelta from aloe import step, world +from django.utils import timezone from nose.tools import assert_equal from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as ec @@ -35,7 +36,7 @@ def fill_out_form(step, form_name, patient_name, again=None): @step(r"(\d+) hour(?:s)? pass(?:es)?") def pass_time(_step, hours): - now = (datetime.now() + timedelta(hours=int(hours))).timestamp() + now = (timezone.now() + timedelta(hours=int(hours))).timestamp() go_to_url(f"mail/send_longitudinal_followups?now={int(now)}") diff --git a/rdrf/rdrf/testing/unit/longitudinal_followup_tests.py b/rdrf/rdrf/testing/unit/longitudinal_followup_tests.py index bbae75b21..dae8b352a 100644 --- a/rdrf/rdrf/testing/unit/longitudinal_followup_tests.py +++ b/rdrf/rdrf/testing/unit/longitudinal_followup_tests.py @@ -1,9 +1,10 @@ import json import logging -from datetime import datetime, timedelta +from datetime import date, timedelta from django.core import mail from django.test import TestCase +from django.utils import timezone from registry.patients.models import ( ConsentValue, LongitudinalFollowupEntry, @@ -35,7 +36,7 @@ class LongitudinalFollowupSetupMixin: def create_models(self): - self.now = datetime.now() + self.now = timezone.now() self.registry = Registry.objects.create( code="reg", metadata_json=json.dumps({"features": ["longitudinal_followups"]}), @@ -99,7 +100,7 @@ def test_single_patient_single_lf(self): debounce=timedelta(weeks=26), ) patient = Patient.objects.create( - consent=True, date_of_birth=datetime(1970, 1, 1), sex="3" + consent=True, date_of_birth=date(1970, 1, 1), sex="3" ) patient.rdrf_registry.add(self.registry) @@ -161,7 +162,7 @@ def test_single_patient_multiple_lf(self): debounce=timedelta(weeks=52), ) patient = Patient.objects.create( - consent=True, date_of_birth=datetime(1970, 1, 1), sex="3" + consent=True, date_of_birth=date(1970, 1, 1), sex="3" ) patient.rdrf_registry.add(self.registry) @@ -249,12 +250,12 @@ def test_multiple_patient_single_lf(self): debounce=timedelta(weeks=26), ) patient1 = Patient.objects.create( - consent=True, date_of_birth=datetime(1970, 1, 1), sex="3" + consent=True, date_of_birth=date(1970, 1, 1), sex="3" ) patient1.rdrf_registry.add(self.registry) patient2 = Patient.objects.create( - consent=True, date_of_birth=datetime(1970, 1, 1), sex="3" + consent=True, date_of_birth=date(1970, 1, 1), sex="3" ) patient2.rdrf_registry.add(self.registry) @@ -352,12 +353,12 @@ def test_multiple_patient_multiple_lf(self): ) patient1 = Patient.objects.create( - consent=True, date_of_birth=datetime(1970, 1, 1), sex="3" + consent=True, date_of_birth=date(1970, 1, 1), sex="3" ) patient1.rdrf_registry.add(self.registry) patient2 = Patient.objects.create( - consent=True, date_of_birth=datetime(1970, 1, 1), sex="3" + consent=True, date_of_birth=date(1970, 1, 1), sex="3" ) patient2.rdrf_registry.add(self.registry) @@ -527,7 +528,7 @@ def create_entry(self, condition): ) patient = Patient.objects.create( - consent=True, date_of_birth=datetime(1970, 1, 1), sex="3" + consent=True, date_of_birth=date(1970, 1, 1), sex="3" ) patient.rdrf_registry.add(self.registry) patient.save() @@ -586,7 +587,7 @@ def create_patient_and_followup(self, frequency_weeks, debounce_weeks): debounce=timedelta(weeks=debounce_weeks), ) patient = Patient.objects.create( - consent=True, date_of_birth=datetime(1970, 1, 1), sex="3" + consent=True, date_of_birth=date(1970, 1, 1), sex="3" ) patient.rdrf_registry.add(self.registry) patient.save() diff --git a/rdrf/rdrf/testing/unit/tests.py b/rdrf/rdrf/testing/unit/tests.py index 282e8f4d7..0b2d1ba85 100644 --- a/rdrf/rdrf/testing/unit/tests.py +++ b/rdrf/rdrf/testing/unit/tests.py @@ -3,7 +3,7 @@ import logging import os from copy import deepcopy -from datetime import datetime, timedelta +from datetime import date, timedelta import yaml from django.conf import settings @@ -14,6 +14,7 @@ from django.core.management import call_command from django.forms.models import model_to_dict from django.test import RequestFactory, TestCase +from django.utils import timezone from registry.groups import GROUPS as RDRF_GROUPS from registry.groups.models import CustomUser, WorkingGroup from registry.patients.models import AddressType, Patient, PatientAddress, State @@ -631,7 +632,7 @@ def create_patient(self): p = Patient() p.consent = True p.name = "Harry" - p.date_of_birth = datetime(1978, 6, 15) + p.date_of_birth = date(1978, 6, 15) p.working_group = self.working_group p.save() p.rdrf_registry.set([self.registry]) @@ -1660,7 +1661,7 @@ def _clear_notifications(self): EmailTemplate.objects.all().delete() def test_check_logins_command(self): - now = datetime.now() + now = timezone.now() class Time: RECENTLY = now - timedelta(days=1) @@ -1797,7 +1798,7 @@ def create_clinicaldata(self, patient_id, registry_code): def create_new_patient(self): p = Patient() p.name = "Kathy" - p.date_of_birth = datetime(1980, 4, 11) + p.date_of_birth = date(1980, 4, 11) p.consent = True p.save() diff --git a/rdrf/rdrf/users/views.py b/rdrf/rdrf/users/views.py index 5423167ac..ce94b7c91 100644 --- a/rdrf/rdrf/users/views.py +++ b/rdrf/rdrf/users/views.py @@ -1,4 +1,3 @@ -import datetime import logging from django.contrib import auth, messages @@ -12,6 +11,7 @@ from django.http import HttpResponse from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse +from django.utils import timezone from django.utils.translation import gettext_lazy as _ from django.views import View from registry.groups.models import ( @@ -44,13 +44,15 @@ def _redirect_response(self): def _render_template(self, request, user, form): # An existing email change request is only considered current if it was requested within the last 2 weeks - last_2_weeks = datetime.datetime.now() + datetime.timedelta(weeks=-2) + from datetime import timedelta + + last_2_weeks = timezone.now() + timedelta(weeks=-2) current_request = EmailChangeRequest.objects.filter( user=user, request_date__gte=last_2_weeks ).first() # Has the activation link most likely expired? - activation_expiry_hours = datetime.datetime.now() + datetime.timedelta( + activation_expiry_hours = timezone.now() + timedelta( hours=-EMAIL_CHANGE_REQUEST_EXPIRY_HOURS ) is_expired = ( diff --git a/rdrf/rdrf/views/mailbox_view.py b/rdrf/rdrf/views/mailbox_view.py index dc4a64609..b830d1b2e 100644 --- a/rdrf/rdrf/views/mailbox_view.py +++ b/rdrf/rdrf/views/mailbox_view.py @@ -1,9 +1,11 @@ import logging from datetime import datetime +from datetime import timezone as dt_timezone from django.core import mail from django.shortcuts import redirect, render from django.urls import reverse +from django.utils import timezone from django.views import View from rdrf.services.io.notifications.longitudinal_followups import ( @@ -34,10 +36,12 @@ def get(self, request): class MailboxSendLongitudinalFollowups(View): def get(self, request): if now_param := request.GET.get("now", None): - now = datetime.fromtimestamp(int(now_param)) + # Use Python's datetime.timezone.utc directly for clarity + now = datetime.fromtimestamp(int(now_param), tz=dt_timezone.utc) else: - now = datetime.now() + now = timezone.now() + logger.info(f"Sending longitudinal followups with now={now}") send_longitudinal_followups(now) return redirect(reverse("mailbox")) diff --git a/rdrf/registry/patients/admin.py b/rdrf/registry/patients/admin.py index f037c35de..22f0187e3 100644 --- a/rdrf/registry/patients/admin.py +++ b/rdrf/registry/patients/admin.py @@ -1,4 +1,3 @@ -import datetime import json import logging import os @@ -8,6 +7,7 @@ from django.db.models import Q from django.http import HttpResponse from django.urls import re_path, reverse +from django.utils import timezone from django.utils.translation import gettext as _ from rdrf.db.dynamic_data import DynamicDataWrapper from rdrf.helpers.registry_features import RegistryFeatures @@ -439,7 +439,7 @@ def freshness(self, obj): if not hasattr(obj, "patient_diagnosis"): return "" - delta = datetime.datetime.now() - obj.patient_diagnosis.updated + delta = timezone.now() - obj.patient_diagnosis.updated age = delta.days if age > 365: @@ -455,7 +455,7 @@ def freshness(self, obj): def last_updated(self, obj): if not hasattr(obj, "diagnosis"): return "" - delta = datetime.datetime.now() - obj.diagnosis.updated + delta = timezone.now() - obj.diagnosis.updated age = delta.days if age == 0: diff --git a/rdrf/registry/patients/models.py b/rdrf/registry/patients/models.py index 35ff7b3c8..9b882b39e 100644 --- a/rdrf/registry/patients/models.py +++ b/rdrf/registry/patients/models.py @@ -1,8 +1,8 @@ -import datetime import json import logging import random from collections import namedtuple +from datetime import date, timedelta from functools import reduce from operator import attrgetter @@ -579,7 +579,7 @@ def calculate_age(born): if self.date_of_death: compare_date = self.date_of_death else: - compare_date = datetime.date.today() + compare_date = date.today() try: birthday = born.replace(year=compare_date.year) @@ -650,9 +650,7 @@ def clinical_data_currency(self, days=365): If some clinical form has been updated in the window then the data for that registry is considered "current" - this mirrors """ - time_window_start = datetime.datetime.now() - datetime.timedelta( - days=days - ) + time_window_start = timezone.now() - timedelta(days=days) currency_map = {} for registry_model in self.rdrf_registry.all(): last_updated_in_window = False @@ -817,7 +815,7 @@ def evaluate_field_expression( mongo_data = { "django_id": self.pk, "django_model": "Patient", - "timestamp": datetime.datetime.now(), + "timestamp": timezone.now(), "context_id": context_model.pk, "forms": [], } @@ -888,7 +886,7 @@ def set_form_value( mongo_data = wrapper.load_dynamic_data(registry_code, "cdes") or {} key = mongo_key(form_name, section_code, data_element_code) timestamp = "%s_timestamp" % form_name - t = datetime.datetime.now() + t = timezone.now() frm = RegistryForm.objects.get( registry__code=registry_code, name=form_name @@ -1032,9 +1030,9 @@ def set_consent(self, consent_model, answer=True, commit=True): answer_changed = cv.answer != answer or created cv.answer = answer if cv.first_save: - cv.last_update = datetime.datetime.now() + cv.last_update = timezone.now() else: - cv.first_save = datetime.datetime.now() + cv.first_save = timezone.now() if commit: cv.save() return cv, answer_changed @@ -1275,7 +1273,7 @@ def form_currency(self, registry_form): if timestamp: if "timestamp" in timestamp: ts = timestamp["timestamp"] - delta = datetime.datetime.now() - ts + delta = timezone.now() - ts return True if delta.days < _6MONTHS_IN_DAYS else False else: return True diff --git a/rdrf/useraudit/models.py b/rdrf/useraudit/models.py index 695d79d9a..6431e2e34 100644 --- a/rdrf/useraudit/models.py +++ b/rdrf/useraudit/models.py @@ -1,10 +1,10 @@ from __future__ import unicode_literals -import datetime import logging from django.contrib.auth.signals import user_logged_in from django.db import models +from django.utils import timezone from .signals import ( account_has_expired, @@ -25,7 +25,7 @@ class LoginAttempt(models.Model): class LoginAttemptLogger(object): def reset(self, username): - defaults = {"count": 0, "timestamp": datetime.datetime.now()} + defaults = {"count": 0, "timestamp": timezone.now()} LoginAttempt.objects.update_or_create( username=username, defaults=defaults ) @@ -33,7 +33,7 @@ def reset(self, username): def increment(self, username): obj, created = LoginAttempt.objects.get_or_create(username=username) obj.count += 1 - obj.timestamp = datetime.datetime.now() + obj.timestamp = timezone.now() obj.save() diff --git a/rdrf/useraudit/tests/utils.py b/rdrf/useraudit/tests/utils.py index 87e33df2f..9fd68928b 100644 --- a/rdrf/useraudit/tests/utils.py +++ b/rdrf/useraudit/tests/utils.py @@ -1,15 +1,15 @@ -from datetime import datetime, timedelta +from datetime import timedelta from functools import reduce from importlib import import_module from django.conf import settings from django.contrib.auth import authenticate, login - from django.test.client import RequestFactory +from django.utils import timezone def is_recent(time): - return datetime.now() - timedelta(seconds=3) < time + return timezone.now() - timedelta(seconds=3) < time def simulate_login(username, password, headers=None): From 2a130cf792ba53df81198619637832e299cea8cf Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 16:05:07 +1000 Subject: [PATCH 07/34] Remove unused helper function --- rdrf/rdrf/helpers/utils.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/rdrf/rdrf/helpers/utils.py b/rdrf/rdrf/helpers/utils.py index f68215151..d235daa21 100644 --- a/rdrf/rdrf/helpers/utils.py +++ b/rdrf/rdrf/helpers/utils.py @@ -406,21 +406,6 @@ def display(form_or_formset, field, error): return results -def timed(func): - logger = logging.getLogger(__name__) - - def wrapper(*args, **kwargs): - a = datetime.datetime.now() - result = func(*args, **kwargs) - b = datetime.datetime.now() - c = b - a - func_name = func.__name__ - logger.debug("%s time = %s secs" % (func_name, c)) - return result - - return wrapper - - def get_cde_value( form_model, section_model, cde_model, patient_record, form_index=None ): From 2e38779de8cd97ff971334a08da79af32a7cb24f Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 16:06:10 +1000 Subject: [PATCH 08/34] Replace logout link with form + POST, as GET is deprecated --- .../rdrf/static/js/session_timeout_manager.js | 23 ++++++++++++++++++- rdrf/rdrf/templates/rdrf_cdes/cde.html | 5 +++- .../templates/rdrf_cdes/navbar_links.html | 9 +++++--- .../testing/behaviour/features/auth/steps.py | 4 +++- rdrf/rdrf/testing/behaviour/features/steps.py | 2 +- 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/rdrf/rdrf/static/js/session_timeout_manager.js b/rdrf/rdrf/static/js/session_timeout_manager.js index 1c07e646b..961c847ed 100644 --- a/rdrf/rdrf/static/js/session_timeout_manager.js +++ b/rdrf/rdrf/static/js/session_timeout_manager.js @@ -169,9 +169,30 @@ function SessionManager(sessionNotifier, options) { } function logout() { - window.location.href = settings.urls.logout; + const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]'); + + if (!csrfToken) { + console.error("CSRF Token not found"); + return; + } + + fetch(settings.urls.logout, { + method: 'POST', + headers: { + 'X-CSRFToken': csrfToken.value + }, + }) + .then(response => { + if (response.ok) { + window.location.href = response.url; + } else { + console.error('Logout failed'); + } + }) + .catch(error => console.error('Error:', error)); } + function goToLoginPage() { window.location.href = settings.urls.login; } diff --git a/rdrf/rdrf/templates/rdrf_cdes/cde.html b/rdrf/rdrf/templates/rdrf_cdes/cde.html index c9c6facbb..0edd1f02a 100644 --- a/rdrf/rdrf/templates/rdrf_cdes/cde.html +++ b/rdrf/rdrf/templates/rdrf_cdes/cde.html @@ -28,7 +28,10 @@

Duchenne Muscular Dystrophy Registry (1.7.0)

Change password / - Log out +
+ {% csrf_token %} + +
diff --git a/rdrf/rdrf/templates/rdrf_cdes/navbar_links.html b/rdrf/rdrf/templates/rdrf_cdes/navbar_links.html index dc6b0d663..890bda77c 100644 --- a/rdrf/rdrf/templates/rdrf_cdes/navbar_links.html +++ b/rdrf/rdrf/templates/rdrf_cdes/navbar_links.html @@ -149,9 +149,12 @@ {% endif %} {% block patient_menu %} {% endblock %} -
  • - {% trans 'Logout' %}
  • +
  • +
    + {% csrf_token %} + +
    +
  • diff --git a/rdrf/rdrf/testing/behaviour/features/auth/steps.py b/rdrf/rdrf/testing/behaviour/features/auth/steps.py index 6d7c255e9..522e6be94 100644 --- a/rdrf/rdrf/testing/behaviour/features/auth/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/auth/steps.py @@ -118,7 +118,9 @@ def login(_step, username, password): @step("logout") def logout(_step): - open_option_from_menu(_step, "Logout", "user") + BasePage(world.browser).open_menu("user") + button = world.browser.find_element(by=By.ID, value="logout-button") + button.click() @step('reauthenticate with username "([^"]+)" and password "([^"]+)"') diff --git a/rdrf/rdrf/testing/behaviour/features/steps.py b/rdrf/rdrf/testing/behaviour/features/steps.py index b7c74912f..4bc32540f 100644 --- a/rdrf/rdrf/testing/behaviour/features/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/steps.py @@ -514,7 +514,7 @@ def should_be_logged_in(step): by=By.PARTIAL_LINK_TEXT, value=world.user ) utils.click(user_link) - world.browser.find_element_by_link_text("Logout") + world.browser.find_element(By.ID, "logout-button") @step("should be on the login page") From 1a3d5be080d6542dab0db499e31780197c7a88c0 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 16:33:06 +1000 Subject: [PATCH 09/34] Add django-simple-history migrations --- .../groups/migrations/0026_history_date.py | 22 +++ .../patients/migrations/0066_history_date.py | 130 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 rdrf/registry/groups/migrations/0026_history_date.py create mode 100644 rdrf/registry/patients/migrations/0066_history_date.py diff --git a/rdrf/registry/groups/migrations/0026_history_date.py b/rdrf/registry/groups/migrations/0026_history_date.py new file mode 100644 index 000000000..60fa6960d --- /dev/null +++ b/rdrf/registry/groups/migrations/0026_history_date.py @@ -0,0 +1,22 @@ +# Generated by Django 5.2.1 on 2026-01-05 06:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('groups', '0025_alter_workinggrouptype'), + ] + + operations = [ + migrations.AlterModelOptions( + name='historicalemailchangerequest', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical email change request', 'verbose_name_plural': 'historical email change requests'}, + ), + migrations.AlterField( + model_name='historicalemailchangerequest', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + ] diff --git a/rdrf/registry/patients/migrations/0066_history_date.py b/rdrf/registry/patients/migrations/0066_history_date.py new file mode 100644 index 000000000..905c0eef6 --- /dev/null +++ b/rdrf/registry/patients/migrations/0066_history_date.py @@ -0,0 +1,130 @@ +# Generated by Django 5.2.1 on 2026-01-05 06:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('patients', '0065_update_parentguardian_field_labels'), + ] + + operations = [ + migrations.AlterModelOptions( + name='historicaladdresstype', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical address type', 'verbose_name_plural': 'historical address types'}, + ), + migrations.AlterModelOptions( + name='historicalclinicianother', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical clinician other', 'verbose_name_plural': 'historical clinician others'}, + ), + migrations.AlterModelOptions( + name='historicalconsentvalue', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical consent value', 'verbose_name_plural': 'historical consent values'}, + ), + migrations.AlterModelOptions( + name='historicaldoctor', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical doctor', 'verbose_name_plural': 'historical doctors'}, + ), + migrations.AlterModelOptions( + name='historicalnextofkinrelationship', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Next of Kin Relationship', 'verbose_name_plural': 'historical Next of Kin Relationships'}, + ), + migrations.AlterModelOptions( + name='historicalparentguardian', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical parent guardian', 'verbose_name_plural': 'historical parent guardians'}, + ), + migrations.AlterModelOptions( + name='historicalpatient', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical patient', 'verbose_name_plural': 'historical Patient List'}, + ), + migrations.AlterModelOptions( + name='historicalpatientaddress', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical patient address', 'verbose_name_plural': 'historical Patient Addresses'}, + ), + migrations.AlterModelOptions( + name='historicalpatientconsent', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical patient consent', 'verbose_name_plural': 'historical patient consents'}, + ), + migrations.AlterModelOptions( + name='historicalpatientdoctor', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical medical professionals for patient', 'verbose_name_plural': 'historical medical professionals for patient'}, + ), + migrations.AlterModelOptions( + name='historicalpatientrelative', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical patient relative', 'verbose_name_plural': 'historical patient relatives'}, + ), + migrations.AlterModelOptions( + name='historicalspeciality', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical speciality', 'verbose_name_plural': 'historical specialitys'}, + ), + migrations.AlterModelOptions( + name='historicalstate', + options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical state', 'verbose_name_plural': 'historical states'}, + ), + migrations.AlterField( + model_name='historicaladdresstype', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalclinicianother', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalconsentvalue', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicaldoctor', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalnextofkinrelationship', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalparentguardian', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalpatient', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalpatientaddress', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalpatientconsent', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalpatientdoctor', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalpatientrelative', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalspeciality', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='historicalstate', + name='history_date', + field=models.DateTimeField(db_index=True), + ), + ] From fc64979a3f2b5377b85f8e5f2f0b053aeb57681c Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 5 Jan 2026 16:33:34 +1000 Subject: [PATCH 10/34] Fix logout --- rdrf/rdrf/testing/behaviour/features/steps.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rdrf/rdrf/testing/behaviour/features/steps.py b/rdrf/rdrf/testing/behaviour/features/steps.py index 4bc32540f..ddf2a0306 100644 --- a/rdrf/rdrf/testing/behaviour/features/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/steps.py @@ -10,6 +10,7 @@ from selenium.webdriver.common.keys import Keys from . import utils +from .auth.steps import logout from .terrain import TEST_WAIT logger = logging.getLogger(__name__) @@ -65,7 +66,7 @@ def check_user_activated(step): ) # Log out as the admin user - world.browser.get(world.site_url + "logout?next=/router/") + logout(step) @step("I try to surf the site...") From 56a23e21c8ad3b6265cca0e4d1b96fabe0cdb78a Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Tue, 6 Jan 2026 09:11:07 +1000 Subject: [PATCH 11/34] Update test zips --- .../behaviour/features/exported_data/ang.zip | Bin 60309 -> 60409 bytes .../behaviour/features/exported_data/dd.zip | Bin 23061 -> 23050 bytes .../behaviour/features/exported_data/fh.zip | Bin 39143 -> 39014 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/rdrf/rdrf/testing/behaviour/features/exported_data/ang.zip b/rdrf/rdrf/testing/behaviour/features/exported_data/ang.zip index 42f45339b36a71b464d9c6983ffec0d1d423d6dd..c710f6c74ddceb312d578482c6304e033ec4edc1 100644 GIT binary patch delta 28307 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 YjLWb7AI<-@fef`cU_p>u_~qgM0C_^{djJ3c delta 28024 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 a)J6ubhv5Cs2O{{dssDfheslh}gZ~E{Nm!i# diff --git a/rdrf/rdrf/testing/behaviour/features/exported_data/dd.zip b/rdrf/rdrf/testing/behaviour/features/exported_data/dd.zip index cce3d0e18bc76dda03fafb677f5a8570baa07762..a5d6564a4e49fdd893937a50bb4a46ed543195d1 100644 GIT binary patch delta 7909 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 delta 8040 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 Pi);K!2elpchvEMNu34=% delta 16425 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 Date: Tue, 6 Jan 2026 09:21:37 +1000 Subject: [PATCH 12/34] Fix circular dependency --- rdrf/rdrf/testing/behaviour/features/auth/steps.py | 3 +-- rdrf/rdrf/testing/behaviour/features/steps.py | 3 +-- rdrf/rdrf/testing/behaviour/features/utils.py | 5 +++++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/rdrf/rdrf/testing/behaviour/features/auth/steps.py b/rdrf/rdrf/testing/behaviour/features/auth/steps.py index 522e6be94..99d6f9c53 100644 --- a/rdrf/rdrf/testing/behaviour/features/auth/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/auth/steps.py @@ -24,9 +24,8 @@ TwoFactorTokenGeneratorPage, get_site_links, ) -from rdrf.testing.behaviour.features.steps import click_link from rdrf.testing.behaviour.features.terrain import TEST_WAIT -from rdrf.testing.behaviour.features.utils import scroll_to_y +from rdrf.testing.behaviour.features.utils import click_link, scroll_to_y logger = logging.getLogger(__name__) diff --git a/rdrf/rdrf/testing/behaviour/features/steps.py b/rdrf/rdrf/testing/behaviour/features/steps.py index ddf2a0306..00afb1891 100644 --- a/rdrf/rdrf/testing/behaviour/features/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/steps.py @@ -96,8 +96,7 @@ def should_see(step, text): @step('click "(.*)"') def click_link(step, link_text): - link = world.browser.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) - utils.click(link) + utils.click_link(link_text) @step('should see a link to "(.*)"') diff --git a/rdrf/rdrf/testing/behaviour/features/utils.py b/rdrf/rdrf/testing/behaviour/features/utils.py index 504faedfe..ba09f4b0d 100644 --- a/rdrf/rdrf/testing/behaviour/features/utils.py +++ b/rdrf/rdrf/testing/behaviour/features/utils.py @@ -216,6 +216,11 @@ def click(element): element.click() +def click_link(link_text): + link = world.browser.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) + click(link) + + def scroll_element_into_view(element, execute_pause=False): world.browser.execute_script( "arguments[0].scrollIntoView({block: 'center'});", element From 25cbbc4b12a7b034e53acc0e8e314012bf315cda Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Tue, 6 Jan 2026 10:02:39 +1000 Subject: [PATCH 13/34] Add logout functionality to auth --- rdrf/rdrf/testing/behaviour/features/auth/steps.py | 3 ++- rdrf/rdrf/testing/behaviour/features/steps.py | 7 ++++--- rdrf/rdrf/testing/behaviour/features/utils.py | 5 ----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/rdrf/rdrf/testing/behaviour/features/auth/steps.py b/rdrf/rdrf/testing/behaviour/features/auth/steps.py index 99d6f9c53..522e6be94 100644 --- a/rdrf/rdrf/testing/behaviour/features/auth/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/auth/steps.py @@ -24,8 +24,9 @@ TwoFactorTokenGeneratorPage, get_site_links, ) +from rdrf.testing.behaviour.features.steps import click_link from rdrf.testing.behaviour.features.terrain import TEST_WAIT -from rdrf.testing.behaviour.features.utils import click_link, scroll_to_y +from rdrf.testing.behaviour.features.utils import scroll_to_y logger = logging.getLogger(__name__) diff --git a/rdrf/rdrf/testing/behaviour/features/steps.py b/rdrf/rdrf/testing/behaviour/features/steps.py index 00afb1891..17cc1767d 100644 --- a/rdrf/rdrf/testing/behaviour/features/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/steps.py @@ -10,7 +10,6 @@ from selenium.webdriver.common.keys import Keys from . import utils -from .auth.steps import logout from .terrain import TEST_WAIT logger = logging.getLogger(__name__) @@ -66,7 +65,8 @@ def check_user_activated(step): ) # Log out as the admin user - logout(step) + world.browser.find_element(By.ID, "authMenuDropdown").click() + world.browser.find_element(By.ID, "logout-button").click() @step("I try to surf the site...") @@ -96,7 +96,8 @@ def should_see(step, text): @step('click "(.*)"') def click_link(step, link_text): - utils.click_link(link_text) + link = world.browser.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) + utils.click(link) @step('should see a link to "(.*)"') diff --git a/rdrf/rdrf/testing/behaviour/features/utils.py b/rdrf/rdrf/testing/behaviour/features/utils.py index ba09f4b0d..504faedfe 100644 --- a/rdrf/rdrf/testing/behaviour/features/utils.py +++ b/rdrf/rdrf/testing/behaviour/features/utils.py @@ -216,11 +216,6 @@ def click(element): element.click() -def click_link(link_text): - link = world.browser.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) - click(link) - - def scroll_element_into_view(element, execute_pause=False): world.browser.execute_script( "arguments[0].scrollIntoView({block: 'center'});", element From 580b8c25ed41418ad2eafe1a4007c4548ebabd50 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Tue, 6 Jan 2026 13:02:57 +1000 Subject: [PATCH 14/34] Timezone-aware patient model tests --- rdrf/rdrf/testing/unit/patient_model_tests.py | 16 +++++++--------- rdrf/registry/patients/models.py | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/rdrf/rdrf/testing/unit/patient_model_tests.py b/rdrf/rdrf/testing/unit/patient_model_tests.py index a9824d488..60495af65 100644 --- a/rdrf/rdrf/testing/unit/patient_model_tests.py +++ b/rdrf/rdrf/testing/unit/patient_model_tests.py @@ -1,10 +1,8 @@ import logging -from datetime import date, datetime +from datetime import date from unittest import mock -from unittest.mock import Mock import pytest -from registry.patients import models from registry.patients.models import Patient from rdrf.models.definition.models import Registry @@ -29,9 +27,9 @@ def _get_calculated_age(self, patient, date_of_birth, date_of_death=None): patient.date_of_death = date_of_death return patient.age - @mock.patch(f"{models.__name__}.datetime", wraps=datetime) - def test_living_patient_age(self, *args, **kwargs): - models.datetime.date.today = Mock(return_value=date(2022, 12, 1)) + @mock.patch("registry.patients.models.timezone") + def test_living_patient_age(self, mock_timezone): + mock_timezone.localdate.return_value = date(2022, 12, 1) self.assertEqual( self._get_calculated_age(self.patient, date(2000, 1, 1)), 22 @@ -51,9 +49,9 @@ def test_living_patient_age(self, *args, **kwargs): self._get_calculated_age(self.patient, date(2017, 2, 29)), 5 ) # Invalid leap year - @mock.patch(f"{models.__name__}.datetime", wraps=datetime) - def test_deceased_patient_age(self, *args, **kwargs): - models.datetime.date.today = Mock(return_value=date(2021, 6, 15)) + @mock.patch("registry.patients.models.timezone") + def test_deceased_patient_age(self, mock_timezone): + mock_timezone.localdate.return_value = date(2021, 6, 15) self.assertEqual( self._get_calculated_age( diff --git a/rdrf/registry/patients/models.py b/rdrf/registry/patients/models.py index 9b882b39e..f2a12776f 100644 --- a/rdrf/registry/patients/models.py +++ b/rdrf/registry/patients/models.py @@ -579,7 +579,7 @@ def calculate_age(born): if self.date_of_death: compare_date = self.date_of_death else: - compare_date = date.today() + compare_date = timezone.localdate() try: birthday = born.replace(year=compare_date.year) From c903e7b98f08e026a26269d6e7dd6c03965ae1e7 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Tue, 6 Jan 2026 13:10:41 +1000 Subject: [PATCH 15/34] Lint fixes --- rdrf/registry/patients/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdrf/registry/patients/models.py b/rdrf/registry/patients/models.py index f2a12776f..b26cbb9af 100644 --- a/rdrf/registry/patients/models.py +++ b/rdrf/registry/patients/models.py @@ -2,7 +2,7 @@ import logging import random from collections import namedtuple -from datetime import date, timedelta +from datetime import timedelta from functools import reduce from operator import attrgetter From fb306a0c7eeaeac91e4df9f81fd92cb8311ef86f Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Tue, 6 Jan 2026 15:05:17 +1000 Subject: [PATCH 16/34] Wait for login/out --- rdrf/rdrf/testing/behaviour/features/auth/steps.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rdrf/rdrf/testing/behaviour/features/auth/steps.py b/rdrf/rdrf/testing/behaviour/features/auth/steps.py index 522e6be94..bb171f1a4 100644 --- a/rdrf/rdrf/testing/behaviour/features/auth/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/auth/steps.py @@ -121,6 +121,11 @@ def logout(_step): BasePage(world.browser).open_menu("user") button = world.browser.find_element(by=By.ID, value="logout-button") button.click() + WebDriverWait(world.browser, TEST_WAIT).until( + expected_conditions.presence_of_element_located( + LoginPage.USERNAME_ELEMENT + ) + ) @step('reauthenticate with username "([^"]+)" and password "([^"]+)"') @@ -131,6 +136,11 @@ def reauthenticate(_step, username, password): @step("am logged in successfully") def assert_is_logged_in(self): + WebDriverWait(world.browser, TEST_WAIT).until( + expected_conditions.presence_of_element_located( + BasePage.SITE_MENU.get("user") + ) + ) assert_equal( BasePage(world.browser).get_user_menu_text(), f"{world.user_first_name} {world.user_last_name}", From ae26e67f0e112b021fd6675af99289f5207a83be Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 9 Jan 2026 10:36:20 +1000 Subject: [PATCH 17/34] Wait for two-factor redirect --- rdrf/rdrf/testing/behaviour/features/auth/page.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rdrf/rdrf/testing/behaviour/features/auth/page.py b/rdrf/rdrf/testing/behaviour/features/auth/page.py index 806f57975..a024a73f0 100644 --- a/rdrf/rdrf/testing/behaviour/features/auth/page.py +++ b/rdrf/rdrf/testing/behaviour/features/auth/page.py @@ -1,6 +1,7 @@ import re from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.expected_conditions import ( text_to_be_present_in_element_value, ) @@ -103,7 +104,12 @@ def set_token(self, token): return self def submit(self): - self._get_element(self.SUBMIT_BUTTON).submit() + submit_button = self._get_element(self.SUBMIT_BUTTON) + submit_button.click() + # Wait for the page to change after form submission + WebDriverWait(self.browser, TEST_WAIT).until( + expected_conditions.staleness_of(submit_button) + ) class TwoFactorTokenGeneratorPage(TwoFactorLoginTokenPage): From 00876970018d2bc27e9b56e4c41090a03a9db272 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 9 Jan 2026 10:44:18 +1000 Subject: [PATCH 18/34] Update xnat client --- clients/xnat/README.md | 2 +- .../generated/.github/workflows/python.yml | 20 +- clients/xnat/generated/.gitlab-ci.yml | 12 +- .../xnat/generated/.openapi-generator/FILES | 8 - .../xnat/generated/.openapi-generator/VERSION | 2 +- clients/xnat/generated/.travis.yml | 6 +- clients/xnat/generated/README.md | 4 +- ...erimentsExperimentIdScansGet200Response.md | 2 +- ...xperimentIdScansGet200ResponseResultSet.md | 2 +- ...ScansGet200ResponseResultSetResultInner.md | 2 +- ...jectsSubjectIdExperimentsGet200Response.md | 2 +- ...ectIdExperimentsGet200ResponseResultSet.md | 2 +- ...mentsGet200ResponseResultSetResultInner.md | 2 +- clients/xnat/generated/docs/DefaultApi.md | 6 - .../xnat/generated/openapi_client/__init__.py | 53 +++-- .../openapi_client/api/default_api.py | 34 +-- .../generated/openapi_client/api_client.py | 116 +++++++--- .../generated/openapi_client/configuration.py | 218 +++++++++++++++--- .../generated/openapi_client/exceptions.py | 26 ++- .../openapi_client/models/__init__.py | 2 +- ...ent_id_scans_get200_response_result_set.py | 6 +- ..._experiments_get200_response_result_set.py | 6 +- clients/xnat/generated/openapi_client/rest.py | 14 +- clients/xnat/generated/pyproject.toml | 59 +++-- clients/xnat/generated/requirements.txt | 5 +- clients/xnat/generated/setup.py | 8 +- clients/xnat/generated/test-requirements.txt | 11 +- 27 files changed, 441 insertions(+), 189 deletions(-) diff --git a/clients/xnat/README.md b/clients/xnat/README.md index 21f6a408c..78b3e40f4 100644 --- a/clients/xnat/README.md +++ b/clients/xnat/README.md @@ -2,5 +2,5 @@ ## Generate an OpenAPI client from the xnat spec 1. Run the openapi generator tool: ```shell -docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli:v7.4.0 generate -i /local/spec/xnat-api.yaml -g python -o /local/generated +docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli:v7.18.0 generate -i /local/spec/xnat-api.yaml -g python -o /local/generated ``` diff --git a/clients/xnat/generated/.github/workflows/python.yml b/clients/xnat/generated/.github/workflows/python.yml index f128ba25e..02a097ebb 100644 --- a/clients/xnat/generated/.github/workflows/python.yml +++ b/clients/xnat/generated/.github/workflows/python.yml @@ -7,16 +7,19 @@ name: openapi_client Python package on: [push, pull_request] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: @@ -24,15 +27,8 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + pip install -r requirements.txt + pip install -r test-requirements.txt - name: Test with pytest run: | - pytest + pytest --cov=openapi_client diff --git a/clients/xnat/generated/.gitlab-ci.yml b/clients/xnat/generated/.gitlab-ci.yml index 29da72111..6b9641eb6 100644 --- a/clients/xnat/generated/.gitlab-ci.yml +++ b/clients/xnat/generated/.gitlab-ci.yml @@ -14,12 +14,6 @@ stages: - pip install -r test-requirements.txt - pytest --cov=openapi_client -pytest-3.7: - extends: .pytest - image: python:3.7-alpine -pytest-3.8: - extends: .pytest - image: python:3.8-alpine pytest-3.9: extends: .pytest image: python:3.9-alpine @@ -29,3 +23,9 @@ pytest-3.10: pytest-3.11: extends: .pytest image: python:3.11-alpine +pytest-3.12: + extends: .pytest + image: python:3.12-alpine +pytest-3.13: + extends: .pytest + image: python:3.13-alpine diff --git a/clients/xnat/generated/.openapi-generator/FILES b/clients/xnat/generated/.openapi-generator/FILES index b7d4f35aa..4a761d983 100644 --- a/clients/xnat/generated/.openapi-generator/FILES +++ b/clients/xnat/generated/.openapi-generator/FILES @@ -1,7 +1,6 @@ .github/workflows/python.yml .gitignore .gitlab-ci.yml -.openapi-generator-ignore .travis.yml README.md docs/DataExperimentsExperimentIdScansGet200Response.md @@ -34,11 +33,4 @@ setup.cfg setup.py test-requirements.txt test/__init__.py -test/test_data_experiments_experiment_id_scans_get200_response.py -test/test_data_experiments_experiment_id_scans_get200_response_result_set.py -test/test_data_experiments_experiment_id_scans_get200_response_result_set_result_inner.py -test/test_data_projects_project_id_subjects_subject_id_experiments_get200_response.py -test/test_data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set.py -test/test_data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner.py -test/test_default_api.py tox.ini diff --git a/clients/xnat/generated/.openapi-generator/VERSION b/clients/xnat/generated/.openapi-generator/VERSION index ba7f754d0..1b2d969d1 100644 --- a/clients/xnat/generated/.openapi-generator/VERSION +++ b/clients/xnat/generated/.openapi-generator/VERSION @@ -1 +1 @@ -7.4.0 +7.18.0 diff --git a/clients/xnat/generated/.travis.yml b/clients/xnat/generated/.travis.yml index fd888f75d..a3e4200d4 100644 --- a/clients/xnat/generated/.travis.yml +++ b/clients/xnat/generated/.travis.yml @@ -1,13 +1,13 @@ # ref: https://docs.travis-ci.com/user/languages/python language: python python: - - "3.7" - - "3.8" - "3.9" - "3.10" - "3.11" + - "3.12" + - "3.13" # uncomment the following if needed - #- "3.11-dev" # 3.11 development branch + #- "3.13-dev" # 3.13 development branch #- "nightly" # nightly build # command to install dependencies install: diff --git a/clients/xnat/generated/README.md b/clients/xnat/generated/README.md index d9355bec8..f65042eb6 100644 --- a/clients/xnat/generated/README.md +++ b/clients/xnat/generated/README.md @@ -5,12 +5,12 @@ This Python package is automatically generated by the [OpenAPI Generator](https: - API version: 1.0.0 - Package version: 1.0.0 -- Generator version: 7.4.0 +- Generator version: 7.18.0 - Build package: org.openapitools.codegen.languages.PythonClientCodegen ## Requirements. -Python 3.7+ +Python 3.9+ ## Installation & Usage ### pip install diff --git a/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200Response.md b/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200Response.md index fb2994791..2ccafea00 100644 --- a/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200Response.md +++ b/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200Response.md @@ -22,7 +22,7 @@ print(DataExperimentsExperimentIdScansGet200Response.to_json()) # convert the object into a dict data_experiments_experiment_id_scans_get200_response_dict = data_experiments_experiment_id_scans_get200_response_instance.to_dict() # create an instance of DataExperimentsExperimentIdScansGet200Response from a dict -data_experiments_experiment_id_scans_get200_response_form_dict = data_experiments_experiment_id_scans_get200_response.from_dict(data_experiments_experiment_id_scans_get200_response_dict) +data_experiments_experiment_id_scans_get200_response_from_dict = DataExperimentsExperimentIdScansGet200Response.from_dict(data_experiments_experiment_id_scans_get200_response_dict) ``` [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200ResponseResultSet.md b/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200ResponseResultSet.md index c41054e98..3da9c8cba 100644 --- a/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200ResponseResultSet.md +++ b/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200ResponseResultSet.md @@ -23,7 +23,7 @@ print(DataExperimentsExperimentIdScansGet200ResponseResultSet.to_json()) # convert the object into a dict data_experiments_experiment_id_scans_get200_response_result_set_dict = data_experiments_experiment_id_scans_get200_response_result_set_instance.to_dict() # create an instance of DataExperimentsExperimentIdScansGet200ResponseResultSet from a dict -data_experiments_experiment_id_scans_get200_response_result_set_form_dict = data_experiments_experiment_id_scans_get200_response_result_set.from_dict(data_experiments_experiment_id_scans_get200_response_result_set_dict) +data_experiments_experiment_id_scans_get200_response_result_set_from_dict = DataExperimentsExperimentIdScansGet200ResponseResultSet.from_dict(data_experiments_experiment_id_scans_get200_response_result_set_dict) ``` [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner.md b/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner.md index 15b575265..2513047d4 100644 --- a/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner.md +++ b/clients/xnat/generated/docs/DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner.md @@ -25,7 +25,7 @@ print(DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner.to_json # convert the object into a dict data_experiments_experiment_id_scans_get200_response_result_set_result_inner_dict = data_experiments_experiment_id_scans_get200_response_result_set_result_inner_instance.to_dict() # create an instance of DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner from a dict -data_experiments_experiment_id_scans_get200_response_result_set_result_inner_form_dict = data_experiments_experiment_id_scans_get200_response_result_set_result_inner.from_dict(data_experiments_experiment_id_scans_get200_response_result_set_result_inner_dict) +data_experiments_experiment_id_scans_get200_response_result_set_result_inner_from_dict = DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner.from_dict(data_experiments_experiment_id_scans_get200_response_result_set_result_inner_dict) ``` [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response.md b/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response.md index 879269818..b59df1c6b 100644 --- a/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response.md +++ b/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response.md @@ -22,7 +22,7 @@ print(DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response.to_json()) # convert the object into a dict data_projects_project_id_subjects_subject_id_experiments_get200_response_dict = data_projects_project_id_subjects_subject_id_experiments_get200_response_instance.to_dict() # create an instance of DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response from a dict -data_projects_project_id_subjects_subject_id_experiments_get200_response_form_dict = data_projects_project_id_subjects_subject_id_experiments_get200_response.from_dict(data_projects_project_id_subjects_subject_id_experiments_get200_response_dict) +data_projects_project_id_subjects_subject_id_experiments_get200_response_from_dict = DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response.from_dict(data_projects_project_id_subjects_subject_id_experiments_get200_response_dict) ``` [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet.md b/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet.md index 7f352b666..088bb1d29 100644 --- a/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet.md +++ b/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet.md @@ -23,7 +23,7 @@ print(DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet.t # convert the object into a dict data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_dict = data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_instance.to_dict() # create an instance of DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet from a dict -data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_form_dict = data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set.from_dict(data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_dict) +data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_from_dict = DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet.from_dict(data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_dict) ``` [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner.md b/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner.md index 2e44cbfab..ebf69fa65 100644 --- a/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner.md +++ b/clients/xnat/generated/docs/DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner.md @@ -25,7 +25,7 @@ print(DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetRe # convert the object into a dict data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner_dict = data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner_instance.to_dict() # create an instance of DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner from a dict -data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner_form_dict = data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner.from_dict(data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner_dict) +data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner_from_dict = DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner.from_dict(data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner_dict) ``` [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/clients/xnat/generated/docs/DefaultApi.md b/clients/xnat/generated/docs/DefaultApi.md index c42f4493f..dc79686ff 100644 --- a/clients/xnat/generated/docs/DefaultApi.md +++ b/clients/xnat/generated/docs/DefaultApi.md @@ -12,8 +12,6 @@ Method | HTTP request | Description # **data_experiments_experiment_id_scans_get** > DataExperimentsExperimentIdScansGet200Response data_experiments_experiment_id_scans_get(experiment_id, format=format) - - Get A Listing Of Scans From An Image Session ### Example @@ -92,8 +90,6 @@ Name | Type | Description | Notes # **data_projects_project_id_subjects_subject_id_experiments_get** > DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response data_projects_project_id_subjects_subject_id_experiments_get(project_id, subject_id, format=format) - - Get a list of experiments ### Example @@ -174,8 +170,6 @@ Name | Type | Description | Notes # **data_services_auth_put** > data_services_auth_put() - - Logs in and returns the authentication cookie ### Example diff --git a/clients/xnat/generated/openapi_client/__init__.py b/clients/xnat/generated/openapi_client/__init__.py index 901a60a36..9ee5313b9 100644 --- a/clients/xnat/generated/openapi_client/__init__.py +++ b/clients/xnat/generated/openapi_client/__init__.py @@ -16,24 +16,45 @@ __version__ = "1.0.0" +# Define package exports +__all__ = [ + "DefaultApi", + "ApiResponse", + "ApiClient", + "Configuration", + "OpenApiException", + "ApiTypeError", + "ApiValueError", + "ApiKeyError", + "ApiAttributeError", + "ApiException", + "DataExperimentsExperimentIdScansGet200Response", + "DataExperimentsExperimentIdScansGet200ResponseResultSet", + "DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner", + "DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response", + "DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet", + "DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner", +] + # import apis into sdk package -from openapi_client.api.default_api import DefaultApi +from openapi_client.api.default_api import DefaultApi as DefaultApi # import ApiClient -from openapi_client.api_response import ApiResponse -from openapi_client.api_client import ApiClient -from openapi_client.configuration import Configuration -from openapi_client.exceptions import OpenApiException -from openapi_client.exceptions import ApiTypeError -from openapi_client.exceptions import ApiValueError -from openapi_client.exceptions import ApiKeyError -from openapi_client.exceptions import ApiAttributeError -from openapi_client.exceptions import ApiException +from openapi_client.api_response import ApiResponse as ApiResponse +from openapi_client.api_client import ApiClient as ApiClient +from openapi_client.configuration import Configuration as Configuration +from openapi_client.exceptions import OpenApiException as OpenApiException +from openapi_client.exceptions import ApiTypeError as ApiTypeError +from openapi_client.exceptions import ApiValueError as ApiValueError +from openapi_client.exceptions import ApiKeyError as ApiKeyError +from openapi_client.exceptions import ApiAttributeError as ApiAttributeError +from openapi_client.exceptions import ApiException as ApiException # import models into sdk package -from openapi_client.models.data_experiments_experiment_id_scans_get200_response import DataExperimentsExperimentIdScansGet200Response -from openapi_client.models.data_experiments_experiment_id_scans_get200_response_result_set import DataExperimentsExperimentIdScansGet200ResponseResultSet -from openapi_client.models.data_experiments_experiment_id_scans_get200_response_result_set_result_inner import DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner -from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response -from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet -from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner +from openapi_client.models.data_experiments_experiment_id_scans_get200_response import DataExperimentsExperimentIdScansGet200Response as DataExperimentsExperimentIdScansGet200Response +from openapi_client.models.data_experiments_experiment_id_scans_get200_response_result_set import DataExperimentsExperimentIdScansGet200ResponseResultSet as DataExperimentsExperimentIdScansGet200ResponseResultSet +from openapi_client.models.data_experiments_experiment_id_scans_get200_response_result_set_result_inner import DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner as DataExperimentsExperimentIdScansGet200ResponseResultSetResultInner +from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response as DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response +from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet as DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet +from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner as DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner + diff --git a/clients/xnat/generated/openapi_client/api/default_api.py b/clients/xnat/generated/openapi_client/api/default_api.py index c0dc66e8c..2a9fa2ebc 100644 --- a/clients/xnat/generated/openapi_client/api/default_api.py +++ b/clients/xnat/generated/openapi_client/api/default_api.py @@ -268,7 +268,9 @@ def _data_experiments_experiment_id_scans_get_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, str] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -285,11 +287,12 @@ def _data_experiments_experiment_id_scans_get_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -556,7 +559,9 @@ def _data_projects_project_id_subjects_subject_id_experiments_get_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, str] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters @@ -575,11 +580,12 @@ def _data_projects_project_id_subjects_subject_id_experiments_get_serialize( # set the HTTP header `Accept` - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) # authentication setting @@ -807,7 +813,9 @@ def _data_services_auth_put_serialize( _query_params: List[Tuple[str, str]] = [] _header_params: Dict[str, Optional[str]] = _headers or {} _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, str] = {} + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} _body_params: Optional[bytes] = None # process the path parameters diff --git a/clients/xnat/generated/openapi_client/api_client.py b/clients/xnat/generated/openapi_client/api_client.py index b03fa098b..056f53c67 100644 --- a/clients/xnat/generated/openapi_client/api_client.py +++ b/clients/xnat/generated/openapi_client/api_client.py @@ -15,14 +15,17 @@ import datetime from dateutil.parser import parse from enum import Enum +import decimal import json import mimetypes import os import re import tempfile +import uuid from urllib.parse import quote -from typing import Tuple, Optional, List, Dict +from typing import Tuple, Optional, List, Dict, Union +from pydantic import SecretStr from openapi_client.configuration import Configuration from openapi_client.api_response import ApiResponse, T as ApiResponseT @@ -65,6 +68,7 @@ class ApiClient: 'bool': bool, 'date': datetime.date, 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, 'object': object, } _pool = None @@ -207,7 +211,8 @@ def param_serialize( post_params, collection_formats ) - post_params.extend(self.files_parameters(files)) + if files: + post_params.extend(self.files_parameters(files)) # auth setting self.update_params_for_auth( @@ -225,7 +230,7 @@ def param_serialize( body = self.sanitize_for_serialization(body) # request url - if _host is None: + if _host is None or self.configuration.ignore_operation_servers: url = self.configuration.host + resource_path else: # use server/host defined in path or operation instead @@ -307,12 +312,12 @@ def response_deserialize( return_data = self.__deserialize_file(response_data) elif response_type is not None: match = None - content_type = response_data.getheader('content-type') + content_type = response_data.headers.get('content-type') if content_type is not None: match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type) encoding = match.group(1) if match else "utf-8" response_text = response_data.data.decode(encoding) - return_data = self.deserialize(response_text, response_type) + return_data = self.deserialize(response_text, response_type, content_type) finally: if not 200 <= response_data.status <= 299: raise ApiException.from_response( @@ -324,7 +329,7 @@ def response_deserialize( return ApiResponse( status_code = response_data.status, data = return_data, - headers = response_data.getheaders(), + headers = response_data.headers, raw_data = response_data.data ) @@ -332,9 +337,11 @@ def sanitize_for_serialization(self, obj): """Builds a JSON POST object. If obj is None, return None. + If obj is SecretStr, return obj.get_secret_value() If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. @@ -344,8 +351,14 @@ def sanitize_for_serialization(self, obj): """ if obj is None: return None + elif isinstance(obj, Enum): + return obj.value + elif isinstance(obj, SecretStr): + return obj.get_secret_value() elif isinstance(obj, self.PRIMITIVE_TYPES): return obj + elif isinstance(obj, uuid.UUID): + return str(obj) elif isinstance(obj, list): return [ self.sanitize_for_serialization(sub_obj) for sub_obj in obj @@ -356,6 +369,8 @@ def sanitize_for_serialization(self, obj): ) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) elif isinstance(obj, dict): obj_dict = obj @@ -365,28 +380,49 @@ def sanitize_for_serialization(self, obj): # and attributes which value is not None. # Convert attribute name to json key in # model definition for request. - obj_dict = obj.to_dict() + if hasattr(obj, 'to_dict') and callable(getattr(obj, 'to_dict')): + obj_dict = obj.to_dict() + else: + obj_dict = obj.__dict__ + + if isinstance(obj_dict, list): + # here we handle instances that can either be a list or something else, and only became a real list by calling to_dict() + return self.sanitize_for_serialization(obj_dict) return { key: self.sanitize_for_serialization(val) for key, val in obj_dict.items() } - def deserialize(self, response_text, response_type): + def deserialize(self, response_text: str, response_type: str, content_type: Optional[str]): """Deserializes response into an object. :param response: RESTResponse object to be deserialized. :param response_type: class literal for deserialized object, or string of class name. + :param content_type: content type of response. :return: deserialized object. """ # fetch data from response object - try: - data = json.loads(response_text) - except ValueError: + if content_type is None: + try: + data = json.loads(response_text) + except ValueError: + data = response_text + elif re.match(r'^application/(json|[\w!#$&.+\-^_]+\+json)\s*(;|$)', content_type, re.IGNORECASE): + if response_text == "": + data = "" + else: + data = json.loads(response_text) + elif re.match(r'^text\/[a-z.+-]+\s*(;|$)', content_type, re.IGNORECASE): data = response_text + else: + raise ApiException( + status=0, + reason="Unsupported content type: {0}".format(content_type) + ) return self.__deserialize(data, response_type) @@ -424,12 +460,14 @@ def __deserialize(self, data, klass): if klass in self.PRIMITIVE_TYPES: return self.__deserialize_primitive(data, klass) - elif klass == object: + elif klass is object: return self.__deserialize_object(data) - elif klass == datetime.date: + elif klass is datetime.date: return self.__deserialize_date(data) - elif klass == datetime.datetime: + elif klass is datetime.datetime: return self.__deserialize_datetime(data) + elif klass is decimal.Decimal: + return decimal.Decimal(data) elif issubclass(klass, Enum): return self.__deserialize_enum(data, klass) else: @@ -486,7 +524,7 @@ def parameters_to_url_query(self, params, collection_formats): if k in collection_formats: collection_format = collection_formats[k] if collection_format == 'multi': - new_params.extend((k, str(value)) for value in v) + new_params.extend((k, quote(str(value))) for value in v) else: if collection_format == 'ssv': delimiter = ' ' @@ -504,31 +542,39 @@ def parameters_to_url_query(self, params, collection_formats): return "&".join(["=".join(map(str, item)) for item in new_params]) - def files_parameters(self, files=None): + def files_parameters( + self, + files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]], + ): """Builds form parameters. :param files: File parameters. :return: Form parameters with files. """ params = [] - - if files: - for k, v in files.items(): - if not v: - continue - file_names = v if type(v) is list else [v] - for n in file_names: - with open(n, 'rb') as f: - filename = os.path.basename(f.name) - filedata = f.read() - mimetype = ( - mimetypes.guess_type(filename)[0] - or 'application/octet-stream' - ) - params.append( - tuple([k, tuple([filename, filedata, mimetype])]) - ) - + for k, v in files.items(): + if isinstance(v, str): + with open(v, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + elif isinstance(v, bytes): + filename = k + filedata = v + elif isinstance(v, tuple): + filename, filedata = v + elif isinstance(v, list): + for file_param in v: + params.extend(self.files_parameters({k: file_param})) + continue + else: + raise ValueError("Unsupported file value") + mimetype = ( + mimetypes.guess_type(filename)[0] + or 'application/octet-stream' + ) + params.append( + tuple([k, tuple([filename, filedata, mimetype])]) + ) return params def select_header_accept(self, accepts: List[str]) -> Optional[str]: @@ -655,7 +701,7 @@ def __deserialize_file(self, response): os.close(fd) os.remove(path) - content_disposition = response.getheader("Content-Disposition") + content_disposition = response.headers.get("Content-Disposition") if content_disposition: m = re.search( r'filename=[\'"]?([^\'"\s]+)[\'"]?', diff --git a/clients/xnat/generated/openapi_client/configuration.py b/clients/xnat/generated/openapi_client/configuration.py index 830c76d59..293e66a22 100644 --- a/clients/xnat/generated/openapi_client/configuration.py +++ b/clients/xnat/generated/openapi_client/configuration.py @@ -13,14 +13,16 @@ import copy +import http.client as httplib import logging from logging import FileHandler import multiprocessing import sys -from typing import Optional +from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict, Union +from typing_extensions import NotRequired, Self + import urllib3 -import http.client as httplib JSON_SCHEMA_VALIDATION_KEYWORDS = { 'multipleOf', 'maximum', 'exclusiveMaximum', @@ -28,10 +30,115 @@ 'minLength', 'pattern', 'maxItems', 'minItems' } +ServerVariablesT = Dict[str, str] + +GenericAuthSetting = TypedDict( + "GenericAuthSetting", + { + "type": str, + "in": str, + "key": str, + "value": str, + }, +) + + +OAuth2AuthSetting = TypedDict( + "OAuth2AuthSetting", + { + "type": Literal["oauth2"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +APIKeyAuthSetting = TypedDict( + "APIKeyAuthSetting", + { + "type": Literal["api_key"], + "in": str, + "key": str, + "value": Optional[str], + }, +) + + +BasicAuthSetting = TypedDict( + "BasicAuthSetting", + { + "type": Literal["basic"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": Optional[str], + }, +) + + +BearerFormatAuthSetting = TypedDict( + "BearerFormatAuthSetting", + { + "type": Literal["bearer"], + "in": Literal["header"], + "format": Literal["JWT"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +BearerAuthSetting = TypedDict( + "BearerAuthSetting", + { + "type": Literal["bearer"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +HTTPSignatureAuthSetting = TypedDict( + "HTTPSignatureAuthSetting", + { + "type": Literal["http-signature"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": None, + }, +) + + +AuthSettings = TypedDict( + "AuthSettings", + { + "basicAuth": BasicAuthSetting, + "cookieAuth": APIKeyAuthSetting, + }, + total=False, +) + + +class HostSettingVariable(TypedDict): + description: str + default_value: str + enum_values: List[str] + + +class HostSetting(TypedDict): + url: str + description: str + variables: NotRequired[Dict[str, HostSettingVariable]] + + class Configuration: """This class contains various settings of the API client. :param host: Base url. + :param ignore_operation_servers + Boolean to ignore operation servers for the API client. + Config will use `host` as the base url regardless of the operation servers. :param api_key: Dict to store API key(s). Each entry in the dict specifies an API key. The dict key is the name of the security scheme in the OAS specification. @@ -54,6 +161,11 @@ class Configuration: values before. :param ssl_ca_cert: str - the path to a file of concatenated CA certificates in PEM format. + :param retries: Number of retries for API requests. + :param ca_cert_data: verify the peer using concatenated CA certificate data + in PEM (str) or DER (bytes) format. + :param cert_file: the path to a client certificate file, for mTLS. + :param key_file: the path to a client key file, for mTLS. :Example: @@ -93,16 +205,29 @@ class Configuration: """ - _default = None - - def __init__(self, host=None, - api_key=None, api_key_prefix=None, - username=None, password=None, - access_token=None, - server_index=None, server_variables=None, - server_operation_index=None, server_operation_variables=None, - ssl_ca_cert=None, - ) -> None: + _default: ClassVar[Optional[Self]] = None + + def __init__( + self, + host: Optional[str]=None, + api_key: Optional[Dict[str, str]]=None, + api_key_prefix: Optional[Dict[str, str]]=None, + username: Optional[str]=None, + password: Optional[str]=None, + access_token: Optional[str]=None, + server_index: Optional[int]=None, + server_variables: Optional[ServerVariablesT]=None, + server_operation_index: Optional[Dict[int, int]]=None, + server_operation_variables: Optional[Dict[int, ServerVariablesT]]=None, + ignore_operation_servers: bool=False, + ssl_ca_cert: Optional[str]=None, + retries: Optional[int] = None, + ca_cert_data: Optional[Union[str, bytes]] = None, + cert_file: Optional[str]=None, + key_file: Optional[str]=None, + *, + debug: Optional[bool] = None, + ) -> None: """Constructor """ self._base_path = "http://localhost" if host is None else host @@ -116,6 +241,9 @@ def __init__(self, host=None, self.server_operation_variables = server_operation_variables or {} """Default server variables """ + self.ignore_operation_servers = ignore_operation_servers + """Ignore operation servers + """ self.temp_folder_path = None """Temp file folder for downloading files """ @@ -159,7 +287,10 @@ def __init__(self, host=None, self.logger_file = None """Debug file location """ - self.debug = False + if debug is not None: + self.debug = debug + else: + self.__debug = False """Debug switch """ @@ -171,10 +302,14 @@ def __init__(self, host=None, self.ssl_ca_cert = ssl_ca_cert """Set this to customize the certificate file to verify the peer. """ - self.cert_file = None + self.ca_cert_data = ca_cert_data + """Set this to verify the peer using PEM (str) or DER (bytes) + certificate data. + """ + self.cert_file = cert_file """client certificate file """ - self.key_file = None + self.key_file = key_file """client key file """ self.assert_hostname = None @@ -202,7 +337,7 @@ def __init__(self, host=None, self.safe_chars_for_path_param = '' """Safe chars for path_param """ - self.retries = None + self.retries = retries """Adding retries to override urllib3 default value 3 """ # Enable client side validation @@ -220,7 +355,7 @@ def __init__(self, host=None, """date format """ - def __deepcopy__(self, memo): + def __deepcopy__(self, memo: Dict[int, Any]) -> Self: cls = self.__class__ result = cls.__new__(cls) memo[id(self)] = result @@ -234,11 +369,11 @@ def __deepcopy__(self, memo): result.debug = self.debug return result - def __setattr__(self, name, value): + def __setattr__(self, name: str, value: Any) -> None: object.__setattr__(self, name, value) @classmethod - def set_default(cls, default): + def set_default(cls, default: Optional[Self]) -> None: """Set default instance of configuration. It stores default configuration, which can be @@ -249,7 +384,7 @@ def set_default(cls, default): cls._default = default @classmethod - def get_default_copy(cls): + def get_default_copy(cls) -> Self: """Deprecated. Please use `get_default` instead. Deprecated. Please use `get_default` instead. @@ -259,7 +394,7 @@ def get_default_copy(cls): return cls.get_default() @classmethod - def get_default(cls): + def get_default(cls) -> Self: """Return the default configuration. This method returns newly created, based on default constructor, @@ -269,11 +404,11 @@ def get_default(cls): :return: The configuration object. """ if cls._default is None: - cls._default = Configuration() + cls._default = cls() return cls._default @property - def logger_file(self): + def logger_file(self) -> Optional[str]: """The logger file. If the logger_file is None, then add stream handler and remove file @@ -285,7 +420,7 @@ def logger_file(self): return self.__logger_file @logger_file.setter - def logger_file(self, value): + def logger_file(self, value: Optional[str]) -> None: """The logger file. If the logger_file is None, then add stream handler and remove file @@ -304,7 +439,7 @@ def logger_file(self, value): logger.addHandler(self.logger_file_handler) @property - def debug(self): + def debug(self) -> bool: """Debug status :param value: The debug status, True or False. @@ -313,7 +448,7 @@ def debug(self): return self.__debug @debug.setter - def debug(self, value): + def debug(self, value: bool) -> None: """Debug status :param value: The debug status, True or False. @@ -335,7 +470,7 @@ def debug(self, value): httplib.HTTPConnection.debuglevel = 0 @property - def logger_format(self): + def logger_format(self) -> str: """The logger format. The logger_formatter will be updated when sets logger_format. @@ -346,7 +481,7 @@ def logger_format(self): return self.__logger_format @logger_format.setter - def logger_format(self, value): + def logger_format(self, value: str) -> None: """The logger format. The logger_formatter will be updated when sets logger_format. @@ -357,7 +492,7 @@ def logger_format(self, value): self.__logger_format = value self.logger_formatter = logging.Formatter(self.__logger_format) - def get_api_key_with_prefix(self, identifier, alias=None): + def get_api_key_with_prefix(self, identifier: str, alias: Optional[str]=None) -> Optional[str]: """Gets API key (with prefix if set). :param identifier: The identifier of apiKey. @@ -374,7 +509,9 @@ def get_api_key_with_prefix(self, identifier, alias=None): else: return key - def get_basic_auth_token(self): + return None + + def get_basic_auth_token(self) -> Optional[str]: """Gets HTTP basic authentication header (string). :return: The token for basic HTTP authentication. @@ -385,16 +522,17 @@ def get_basic_auth_token(self): password = "" if self.password is not None: password = self.password + return urllib3.util.make_headers( basic_auth=username + ':' + password ).get('authorization') - def auth_settings(self): + def auth_settings(self)-> AuthSettings: """Gets Auth Settings dict for api client. :return: The Auth Settings information dict. """ - auth = {} + auth: AuthSettings = {} if self.username is not None and self.password is not None: auth['basicAuth'] = { 'type': 'basic', @@ -413,7 +551,7 @@ def auth_settings(self): } return auth - def to_debug_report(self): + def to_debug_report(self) -> str: """Gets the essential information for debugging. :return: The report for debugging. @@ -425,7 +563,7 @@ def to_debug_report(self): "SDK Package Version: 1.0.0".\ format(env=sys.platform, pyversion=sys.version) - def get_host_settings(self): + def get_host_settings(self) -> List[HostSetting]: """Gets an array of host settings :return: An array of host settings @@ -437,7 +575,12 @@ def get_host_settings(self): } ] - def get_host_from_settings(self, index, variables=None, servers=None): + def get_host_from_settings( + self, + index: Optional[int], + variables: Optional[ServerVariablesT]=None, + servers: Optional[List[HostSetting]]=None, + ) -> str: """Gets host URL based on the index and variables :param index: array index of the host settings :param variables: hash of variable and the corresponding value @@ -465,6 +608,7 @@ def get_host_from_settings(self, index, variables=None, servers=None): variable_name, variable['default_value']) if 'enum_values' in variable \ + and variable['enum_values'] \ and used_value not in variable['enum_values']: raise ValueError( "The variable `{0}` in the host URL has invalid value " @@ -477,12 +621,12 @@ def get_host_from_settings(self, index, variables=None, servers=None): return url @property - def host(self): + def host(self) -> str: """Return generated host.""" return self.get_host_from_settings(self.server_index, variables=self.server_variables) @host.setter - def host(self, value): + def host(self, value: str) -> None: """Fix base path.""" self._base_path = value self.server_index = None diff --git a/clients/xnat/generated/openapi_client/exceptions.py b/clients/xnat/generated/openapi_client/exceptions.py index 30d9a5db3..32c84d28f 100644 --- a/clients/xnat/generated/openapi_client/exceptions.py +++ b/clients/xnat/generated/openapi_client/exceptions.py @@ -128,7 +128,7 @@ def __init__( self.body = http_resp.data.decode('utf-8') except Exception: pass - self.headers = http_resp.getheaders() + self.headers = http_resp.headers @classmethod def from_response( @@ -150,6 +150,13 @@ def from_response( if http_resp.status == 404: raise NotFoundException(http_resp=http_resp, body=body, data=data) + # Added new conditions for 409 and 422 + if http_resp.status == 409: + raise ConflictException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 422: + raise UnprocessableEntityException(http_resp=http_resp, body=body, data=data) + if 500 <= http_resp.status <= 599: raise ServiceException(http_resp=http_resp, body=body, data=data) raise ApiException(http_resp=http_resp, body=body, data=data) @@ -162,8 +169,11 @@ def __str__(self): error_message += "HTTP response headers: {0}\n".format( self.headers) - if self.data or self.body: - error_message += "HTTP response body: {0}\n".format(self.data or self.body) + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + if self.data: + error_message += "HTTP response data: {0}\n".format(self.data) return error_message @@ -188,6 +198,16 @@ class ServiceException(ApiException): pass +class ConflictException(ApiException): + """Exception for HTTP 409 Conflict.""" + pass + + +class UnprocessableEntityException(ApiException): + """Exception for HTTP 422 Unprocessable Entity.""" + pass + + def render_path(path_to_item): """Returns a string representation of a path""" result = "" diff --git a/clients/xnat/generated/openapi_client/models/__init__.py b/clients/xnat/generated/openapi_client/models/__init__.py index 4c37c2cfa..cca18d9b2 100644 --- a/clients/xnat/generated/openapi_client/models/__init__.py +++ b/clients/xnat/generated/openapi_client/models/__init__.py @@ -12,7 +12,6 @@ Do not edit the class manually. """ # noqa: E501 - # import models into model package from openapi_client.models.data_experiments_experiment_id_scans_get200_response import DataExperimentsExperimentIdScansGet200Response from openapi_client.models.data_experiments_experiment_id_scans_get200_response_result_set import DataExperimentsExperimentIdScansGet200ResponseResultSet @@ -20,3 +19,4 @@ from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200Response from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSet from openapi_client.models.data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set_result_inner import DataProjectsProjectIdSubjectsSubjectIdExperimentsGet200ResponseResultSetResultInner + diff --git a/clients/xnat/generated/openapi_client/models/data_experiments_experiment_id_scans_get200_response_result_set.py b/clients/xnat/generated/openapi_client/models/data_experiments_experiment_id_scans_get200_response_result_set.py index 80363b848..11257fc8f 100644 --- a/clients/xnat/generated/openapi_client/models/data_experiments_experiment_id_scans_get200_response_result_set.py +++ b/clients/xnat/generated/openapi_client/models/data_experiments_experiment_id_scans_get200_response_result_set.py @@ -73,9 +73,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in result (list) _items = [] if self.result: - for _item in self.result: - if _item: - _items.append(_item.to_dict()) + for _item_result in self.result: + if _item_result: + _items.append(_item_result.to_dict()) _dict['Result'] = _items return _dict diff --git a/clients/xnat/generated/openapi_client/models/data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set.py b/clients/xnat/generated/openapi_client/models/data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set.py index 1bfd822e0..9777337b8 100644 --- a/clients/xnat/generated/openapi_client/models/data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set.py +++ b/clients/xnat/generated/openapi_client/models/data_projects_project_id_subjects_subject_id_experiments_get200_response_result_set.py @@ -73,9 +73,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in result (list) _items = [] if self.result: - for _item in self.result: - if _item: - _items.append(_item.to_dict()) + for _item_result in self.result: + if _item_result: + _items.append(_item_result.to_dict()) _dict['Result'] = _items return _dict diff --git a/clients/xnat/generated/openapi_client/rest.py b/clients/xnat/generated/openapi_client/rest.py index 966666995..ed8a4326f 100644 --- a/clients/xnat/generated/openapi_client/rest.py +++ b/clients/xnat/generated/openapi_client/rest.py @@ -48,12 +48,17 @@ def read(self): self.data = self.response.data return self.data + @property + def headers(self): + """Returns a dictionary of response headers.""" + return self.response.headers + def getheaders(self): - """Returns a dictionary of the response headers.""" + """Returns a dictionary of the response headers; use ``headers`` instead.""" return self.response.headers def getheader(self, name, default=None): - """Returns a given response header.""" + """Returns a given response header; use ``headers.get()`` instead.""" return self.response.headers.get(name, default) @@ -76,6 +81,7 @@ def __init__(self, configuration) -> None: "ca_certs": configuration.ssl_ca_cert, "cert_file": configuration.cert_file, "key_file": configuration.key_file, + "ca_cert_data": configuration.ca_cert_data, } if configuration.assert_hostname is not None: pool_args['assert_hostname'] = ( @@ -202,6 +208,8 @@ def request( # Content-Type which generated by urllib3 will be # overwritten. del headers['Content-Type'] + # Ensures that dict objects are serialized + post_params = [(a, json.dumps(b)) if isinstance(b, dict) else (a,b) for a, b in post_params] r = self.pool_manager.request( method, url, @@ -223,7 +231,7 @@ def request( headers=headers, preload_content=False ) - elif headers['Content-Type'] == 'text/plain' and isinstance(body, bool): + elif headers['Content-Type'].startswith('text/') and isinstance(body, bool): request_body = "true" if body else "false" r = self.pool_manager.request( method, diff --git a/clients/xnat/generated/pyproject.toml b/clients/xnat/generated/pyproject.toml index 2096bc99f..9847fa40e 100644 --- a/clients/xnat/generated/pyproject.toml +++ b/clients/xnat/generated/pyproject.toml @@ -1,28 +1,34 @@ -[tool.poetry] +[project] name = "openapi_client" version = "1.0.0" description = "XNAT REST API Translation" -authors = ["OpenAPI Generator Community "] -license = "NoLicense" +authors = [ + {name = "OpenAPI Generator Community",email = "team@openapitools.org"}, +] readme = "README.md" -repository = "https://github.com/GIT_USER_ID/GIT_REPO_ID" keywords = ["OpenAPI", "OpenAPI-Generator", "XNAT REST API Translation"] -include = ["openapi_client/py.typed"] +requires-python = ">=3.9" -[tool.poetry.dependencies] -python = "^3.7" +dependencies = [ + "urllib3 (>=2.1.0,<3.0.0)", + "python-dateutil (>=2.8.2)", + "pydantic (>=2)", + "typing-extensions (>=4.7.1)", +] -urllib3 = ">= 1.25.3" -python-dateutil = ">=2.8.2" -pydantic = ">=2" -typing-extensions = ">=4.7.1" +[project.urls] +Repository = "https://github.com/GIT_USER_ID/GIT_REPO_ID" -[tool.poetry.dev-dependencies] -pytest = ">=7.2.1" -tox = ">=3.9.0" -flake8 = ">=4.0.0" -types-python-dateutil = ">=2.8.19.14" -mypy = "1.4.1" +[tool.poetry] +requires-poetry = ">=2.0" + +[tool.poetry.group.dev.dependencies] +pytest = ">= 7.2.1" +pytest-cov = ">= 2.8.1" +tox = ">= 3.9.0" +flake8 = ">= 4.0.0" +types-python-dateutil = ">= 2.8.19.14" +mypy = ">= 1.5" [build-system] @@ -48,7 +54,7 @@ warn_unused_ignores = true ## Getting these passing should be easy strict_equality = true -strict_concatenate = true +extra_checks = true ## Strongly recommend enabling this one as soon as you can check_untyped_defs = true @@ -69,3 +75,20 @@ disallow_any_generics = true # ### This one can be tricky to get passing if you use a lot of untyped libraries #warn_return_any = true + +[[tool.mypy.overrides]] +module = [ + "openapi_client.configuration", +] +warn_unused_ignores = true +strict_equality = true +extra_checks = true +check_untyped_defs = true +disallow_subclassing_any = true +disallow_untyped_decorators = true +disallow_any_generics = true +disallow_untyped_calls = true +disallow_incomplete_defs = true +disallow_untyped_defs = true +no_implicit_reexport = true +warn_return_any = true diff --git a/clients/xnat/generated/requirements.txt b/clients/xnat/generated/requirements.txt index cc85509ec..6cbb2b98b 100644 --- a/clients/xnat/generated/requirements.txt +++ b/clients/xnat/generated/requirements.txt @@ -1,5 +1,4 @@ -python_dateutil >= 2.5.3 -setuptools >= 21.0.0 -urllib3 >= 1.25.3, < 2.1.0 +urllib3 >= 2.1.0, < 3.0.0 +python_dateutil >= 2.8.2 pydantic >= 2 typing-extensions >= 4.7.1 diff --git a/clients/xnat/generated/setup.py b/clients/xnat/generated/setup.py index 6f3312d81..bf2127aa3 100644 --- a/clients/xnat/generated/setup.py +++ b/clients/xnat/generated/setup.py @@ -22,10 +22,10 @@ # http://pypi.python.org/pypi/setuptools NAME = "openapi-client" VERSION = "1.0.0" -PYTHON_REQUIRES = ">=3.7" +PYTHON_REQUIRES = ">= 3.9" REQUIRES = [ - "urllib3 >= 1.25.3, < 2.1.0", - "python-dateutil", + "urllib3 >= 2.1.0, < 3.0.0", + "python-dateutil >= 2.8.2", "pydantic >= 2", "typing-extensions >= 4.7.1", ] @@ -46,4 +46,4 @@ REST API converted to Open API """, # noqa: E501 package_data={"openapi_client": ["py.typed"]}, -) +) \ No newline at end of file diff --git a/clients/xnat/generated/test-requirements.txt b/clients/xnat/generated/test-requirements.txt index 8e6d8cb13..e98555c11 100644 --- a/clients/xnat/generated/test-requirements.txt +++ b/clients/xnat/generated/test-requirements.txt @@ -1,5 +1,6 @@ -pytest~=7.1.3 -pytest-cov>=2.8.1 -pytest-randomly>=3.12.0 -mypy>=1.4.1 -types-python-dateutil>=2.8.19 +pytest >= 7.2.1 +pytest-cov >= 2.8.1 +tox >= 3.9.0 +flake8 >= 4.0.0 +types-python-dateutil >= 2.8.19.14 +mypy >= 1.5 From bc9fe82c99fa7a55e148a1ad74880fb5e319f542 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 9 Jan 2026 11:25:49 +1000 Subject: [PATCH 19/34] Update selenium --- pyproject.toml | 2 +- .../testing/behaviour/features/terrain.py | 16 +- uv.lock | 140 +++--------------- 3 files changed, 32 insertions(+), 126 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6b8f8cdd9..66dcbd9d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,7 +75,7 @@ test = [ "aloe_webdriver==0.6.0", "aloe_django==0.2.0", "pyvirtualdisplay==0.2.5", - "selenium==4.1.3", + "selenium>=4.10.0", "unittest-xml-reporting==3.2.0", "requests==2.32.4", "sqlalchemy-utils==0.36.1", diff --git a/rdrf/rdrf/testing/behaviour/features/terrain.py b/rdrf/rdrf/testing/behaviour/features/terrain.py index ca97a90a0..7f5d4fbfe 100644 --- a/rdrf/rdrf/testing/behaviour/features/terrain.py +++ b/rdrf/rdrf/testing/behaviour/features/terrain.py @@ -5,6 +5,8 @@ from aloe import after, around, before, world from django.conf import settings from selenium import webdriver +from selenium.webdriver.chrome.options import Options as ChromeOptions +from selenium.webdriver.firefox.options import Options as FirefoxOptions from . import utils @@ -23,21 +25,21 @@ ) -def get_desired_capabilities(browser): - return { - "firefox": webdriver.DesiredCapabilities.FIREFOX, - "chrome": webdriver.DesiredCapabilities.CHROME, - }.get(browser, webdriver.DesiredCapabilities.FIREFOX) +def get_browser_options(browser): + if browser == "chrome": + return ChromeOptions() + else: + return FirefoxOptions() @around.all @contextmanager def with_browser(): - desired_capabilities = get_desired_capabilities(TEST_BROWSER) + options = get_browser_options(TEST_BROWSER) world.browser = webdriver.Remote( - desired_capabilities=desired_capabilities, command_executor=TEST_SELENIUM_HUB, + options=options, ) world.browser.implicitly_wait(TEST_WAIT) diff --git a/uv.lock b/uv.lock index dcc99e7a5..4c157ae6a 100644 --- a/uv.lock +++ b/uv.lock @@ -213,37 +213,12 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, - { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, - { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, - { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, - { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, - { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, - { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, - { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, - { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, - { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, - { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, - { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, - { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, - { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, - { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, - { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, - { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, - { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, @@ -317,62 +292,6 @@ version = "5.5" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/38/df/d5e67851e83948def768d7fb1a0fd373665b20f56ff63ed220c6cd16cb11/coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c", size = 691258, upload-time = "2021-02-28T20:13:23.11Z" } -[[package]] -name = "cryptography" -version = "46.0.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" }, - { url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" }, - { url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" }, - { url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" }, - { url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" }, - { url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" }, - { url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" }, - { url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" }, - { url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" }, - { url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" }, - { url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" }, - { url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" }, - { url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" }, - { url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" }, - { url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" }, - { url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" }, - { url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" }, - { url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" }, - { url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" }, - { url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" }, - { url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" }, - { url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" }, - { url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" }, - { url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" }, - { url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" }, - { url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" }, - { url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" }, - { url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" }, - { url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" }, - { url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" }, - { url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" }, - { url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" }, - { url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" }, - { url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" }, - { url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" }, - { url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" }, - { url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" }, - { url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" }, - { url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" }, - { url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" }, - { url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" }, - { url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" }, - { url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" }, -] - [[package]] name = "cssselect" version = "1.3.0" @@ -1185,9 +1104,9 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "pydantic", specifier = ">=2" }, - { name = "python-dateutil" }, + { name = "python-dateutil", specifier = ">=2.8.2" }, { name = "typing-extensions", specifier = ">=4.7.1" }, - { name = "urllib3", specifier = ">=1.25.3,<2.1.0" }, + { name = "urllib3", specifier = ">=2.1.0,<3.0.0" }, ] [[package]] @@ -1523,18 +1442,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/29/02/70dd00c947bcb4a1e9f883761aa4632a9d61b5bf5f5ad4fae5e8cb06200c/pynose-1.5.5-py3-none-any.whl", hash = "sha256:673751d53fcfc79b1e48c14f36c7a24779ad43676eeb85736934de6a2b3d8ec8", size = 130706, upload-time = "2025-09-08T20:45:13.697Z" }, ] -[[package]] -name = "pyopenssl" -version = "25.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cryptography" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/80/be/97b83a464498a79103036bc74d1038df4a7ef0e402cfaf4d5e113fb14759/pyopenssl-25.3.0.tar.gz", hash = "sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329", size = 184073, upload-time = "2025-09-17T00:32:21.037Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/81/ef2b1dfd1862567d573a4fdbc9f969067621764fbb74338496840a1d2977/pyopenssl-25.3.0-py3-none-any.whl", hash = "sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6", size = 57268, upload-time = "2025-09-17T00:32:19.474Z" }, -] - [[package]] name = "pyrsistent" version = "0.20.0" @@ -1812,15 +1719,19 @@ wheels = [ [[package]] name = "selenium" -version = "4.1.3" +version = "4.39.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "certifi" }, { name = "trio" }, { name = "trio-websocket" }, - { name = "urllib3", extra = ["secure", "socks"] }, + { name = "typing-extensions" }, + { name = "urllib3", extra = ["socks"] }, + { name = "websocket-client" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/af/19/27c1bf9eb1f7025632d35a956b50746efb4b10aa87f961b263fa7081f4c5/selenium-4.39.0.tar.gz", hash = "sha256:12f3325f02d43b6c24030fc9602b34a3c6865abbb1db9406641d13d108aa1889", size = 928575, upload-time = "2025-12-06T23:12:34.896Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/f2/6f584262771d383ad2d21c8b01f8f4af784884f4e25c1f6450265a558a45/selenium-4.1.3-py3-none-any.whl", hash = "sha256:14d28a628c831c105d38305c881c9c7847199bfd728ec84240c5e86fa1c9bd5a", size = 968834, upload-time = "2022-03-09T15:16:43.216Z" }, + { url = "https://files.pythonhosted.org/packages/58/d0/55a6b7c6f35aad4c8a54be0eb7a52c1ff29a59542fc3e655f0ecbb14456d/selenium-4.39.0-py3-none-any.whl", hash = "sha256:c85f65d5610642ca0f47dae9d5cc117cd9e831f74038bc09fe1af126288200f9", size = 9655249, upload-time = "2025-12-06T23:12:33.085Z" }, ] [[package]] @@ -2267,7 +2178,7 @@ requires-dist = [ { name = "qrcode", specifier = "==6.1" }, { name = "requests", marker = "extra == 'test'", specifier = "==2.32.4" }, { name = "ruff", marker = "extra == 'dev'" }, - { name = "selenium", marker = "extra == 'test'", specifier = "==4.1.3" }, + { name = "selenium", marker = "extra == 'test'", specifier = ">=4.10.0" }, { name = "six", specifier = "==1.16.0" }, { name = "sphinx", marker = "extra == 'dev'" }, { name = "sphinxcontrib-fulltoc", marker = "extra == 'dev'" }, @@ -2336,34 +2247,18 @@ wheels = [ [[package]] name = "urllib3" -version = "1.26.20" +version = "2.6.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/e8/6ff5e6bc22095cfc59b6ea711b687e2b7ed4bdb373f7eeec370a97d7392f/urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", size = 307380, upload-time = "2024-08-29T15:43:11.37Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/cf/8435d5a7159e2a9c83a95896ed596f68cf798005fe107cc655b5c5c14704/urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", size = 144225, upload-time = "2024-08-29T15:43:08.921Z" }, + { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] [package.optional-dependencies] -secure = [ - { name = "certifi" }, - { name = "cryptography" }, - { name = "idna" }, - { name = "pyopenssl" }, - { name = "urllib3-secure-extra" }, -] socks = [ { name = "pysocks" }, ] -[[package]] -name = "urllib3-secure-extra" -version = "0.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c9/67/76b7c055ea787729bb9f839a84689ea2f88e217519d59ae547824431ec95/urllib3-secure-extra-0.1.0.tar.gz", hash = "sha256:ee9409cbfeb4b8609047be4c32fb4317870c602767e53fd8a41005ebe6a41dff", size = 986, upload-time = "2022-08-01T14:51:36.091Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/90/cd/273b6978ace72ef1d3f35610206e44e4527d557500e3d7b39732f2b4dd3c/urllib3_secure_extra-0.1.0-py2.py3-none-any.whl", hash = "sha256:f7adcb108b4d12a4b26b99eb60e265d087f435052a76aefa396b6ee85e9a6ef9", size = 1444, upload-time = "2022-08-01T14:51:33.853Z" }, -] - [[package]] name = "user-agents" version = "2.2.0" @@ -2391,6 +2286,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, ] +[[package]] +name = "websocket-client" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, +] + [[package]] name = "werkzeug" version = "3.1.4" From c5a558ac95b4acdfea82d35f7d5846c4077d720e Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 9 Jan 2026 11:26:03 +1000 Subject: [PATCH 20/34] Re-order waits for 2fa --- rdrf/rdrf/testing/behaviour/features/auth/page.py | 8 +------- rdrf/rdrf/testing/behaviour/features/auth/steps.py | 6 ++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/rdrf/rdrf/testing/behaviour/features/auth/page.py b/rdrf/rdrf/testing/behaviour/features/auth/page.py index a024a73f0..21574fb5e 100644 --- a/rdrf/rdrf/testing/behaviour/features/auth/page.py +++ b/rdrf/rdrf/testing/behaviour/features/auth/page.py @@ -1,7 +1,6 @@ import re from selenium.webdriver.common.by import By -from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.expected_conditions import ( text_to_be_present_in_element_value, ) @@ -104,12 +103,7 @@ def set_token(self, token): return self def submit(self): - submit_button = self._get_element(self.SUBMIT_BUTTON) - submit_button.click() - # Wait for the page to change after form submission - WebDriverWait(self.browser, TEST_WAIT).until( - expected_conditions.staleness_of(submit_button) - ) + self._get_element(self.SUBMIT_BUTTON).click() class TwoFactorTokenGeneratorPage(TwoFactorLoginTokenPage): diff --git a/rdrf/rdrf/testing/behaviour/features/auth/steps.py b/rdrf/rdrf/testing/behaviour/features/auth/steps.py index bb171f1a4..0312e06eb 100644 --- a/rdrf/rdrf/testing/behaviour/features/auth/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/auth/steps.py @@ -225,7 +225,13 @@ def setup_initial_otp_token(_step): @step("enter my generated OTP token") def enter_otp_token(_step): + current_url = world.browser.current_url utils.set_otp_token(TwoFactorLoginTokenPage(world.browser), world.key) + # Wait for the URL to change away from the 2FA login page + # Use longer timeout to handle CI environment delays + WebDriverWait(world.browser, TEST_WAIT * 2).until( + expected_conditions.url_changes(current_url) + ) @step("confirm to disable two-factor auth") From 80ea3cc683e68c71b20322c742365c49820b4103 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 09:25:14 +1000 Subject: [PATCH 21/34] Fix selenium issues and remove aloe_webdriver --- pyproject.toml | 1 - rdrf/rdrf/testing/behaviour/features/steps.py | 3 +- .../testing/behaviour/features/terrain.py | 14 ++++++---- rdrf/rdrf/testing/behaviour/features/utils.py | 28 +++++++++++++++++++ uv.lock | 15 ---------- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 66dcbd9d5..f3233b57a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,7 +72,6 @@ test = [ "pynose==1.5.5", "nose-timer==0.7.5", "aloe==0.2.0", - "aloe_webdriver==0.6.0", "aloe_django==0.2.0", "pyvirtualdisplay==0.2.5", "selenium>=4.10.0", diff --git a/rdrf/rdrf/testing/behaviour/features/steps.py b/rdrf/rdrf/testing/behaviour/features/steps.py index 17cc1767d..a7d06596a 100644 --- a/rdrf/rdrf/testing/behaviour/features/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/steps.py @@ -3,7 +3,6 @@ from aloe import step, world from aloe.registry import STEP_REGISTRY -from aloe_webdriver.webdriver import contains_content from nose.tools import assert_equal, assert_true from selenium.webdriver.common.alert import Alert from selenium.webdriver.common.by import By @@ -91,7 +90,7 @@ def load_export(step, export_name): @step('should see "([^"]+)"$') def should_see(step, text): - assert_true(contains_content(world.browser, text)) + assert_true(utils.contains_content(text)) @step('click "(.*)"') diff --git a/rdrf/rdrf/testing/behaviour/features/terrain.py b/rdrf/rdrf/testing/behaviour/features/terrain.py index 7f5d4fbfe..09388249a 100644 --- a/rdrf/rdrf/testing/behaviour/features/terrain.py +++ b/rdrf/rdrf/testing/behaviour/features/terrain.py @@ -4,7 +4,7 @@ from aloe import after, around, before, world from django.conf import settings -from selenium import webdriver +from selenium.webdriver import Remote from selenium.webdriver.chrome.options import Options as ChromeOptions from selenium.webdriver.firefox.options import Options as FirefoxOptions @@ -26,10 +26,12 @@ def get_browser_options(browser): - if browser == "chrome": - return ChromeOptions() - else: - return FirefoxOptions() + options_map = { + "firefox": FirefoxOptions, + "chrome": ChromeOptions, + } + options_class = options_map.get(browser, FirefoxOptions) + return options_class() @around.all @@ -37,7 +39,7 @@ def get_browser_options(browser): def with_browser(): options = get_browser_options(TEST_BROWSER) - world.browser = webdriver.Remote( + world.browser = Remote( command_executor=TEST_SELENIUM_HUB, options=options, ) diff --git a/rdrf/rdrf/testing/behaviour/features/utils.py b/rdrf/rdrf/testing/behaviour/features/utils.py index 504faedfe..5b43642e5 100644 --- a/rdrf/rdrf/testing/behaviour/features/utils.py +++ b/rdrf/rdrf/testing/behaviour/features/utils.py @@ -4,6 +4,7 @@ from aloe import world from selenium.webdriver.common.by import By +from selenium.common.exceptions import StaleElementReferenceException TEST_WAIT = int(os.environ.get("TEST_WAIT") or "10") @@ -374,3 +375,30 @@ def wait_for_first_section(): (By.CSS_SELECTOR, ".section-available") ) ) + +# From aloe_webdriver: https://github.com/aloetesting/aloe_webdriver + +def string_literal(content): + if '"' in content and "'" in content: + raise ValueError("Cannot represent this string in XPath") + + if '"' in content: + content = "'%s'" % content + else: + content = '"%s"' % content + + return content + +def contains_content(content): + for elem in world.browser.find_elements(By.XPATH, + '//*[contains(normalize-space(.), {content}) ' + 'and not(./*[contains(normalize-space(.), {content})])]' + .format(content=string_literal(content))): + + try: + if elem.is_displayed(): + return True + except StaleElementReferenceException: + pass + + return False diff --git a/uv.lock b/uv.lock index 4c157ae6a..95ef8fc62 100644 --- a/uv.lock +++ b/uv.lock @@ -36,19 +36,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/7f/d5/e28852bfb63e12478a488e165750cc33fb526dea6b14f8cd1a12f1577078/aloe_django-0.2.0.tar.gz", hash = "sha256:004e752cca48155ed249433a8af9cface938c62d903579e5a722f3bce62ba410", size = 44066, upload-time = "2020-01-12T10:56:14.02Z" } -[[package]] -name = "aloe-webdriver" -version = "0.6.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aloe" }, - { name = "selenium" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/05/30/9cfe29e598b95ed3aa892b5dbf191e1b2c4e4ac692169fe29624f5fed448/aloe_webdriver-0.6.0.tar.gz", hash = "sha256:3b4f8ddd73d4c0ebf6afcabcb35283fe676ce9a4c5f4f0c038b0f16855a1a6d3", size = 36551, upload-time = "2020-01-12T22:35:58.849Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/1a/1462553bb538cf01aba6ba8d598638d8c084cfd49ca98a72f6bb51c96168/aloe_webdriver-0.6.0-py3-none-any.whl", hash = "sha256:3875e87223d68a4e06488fe67c2cd81f40d1bbb0faa3417434659916bd570072", size = 32087, upload-time = "2020-01-12T22:35:56.925Z" }, -] - [[package]] name = "annotated-types" version = "0.7.0" @@ -2107,7 +2094,6 @@ dev = [ test = [ { name = "aloe" }, { name = "aloe-django" }, - { name = "aloe-webdriver" }, { name = "coverage" }, { name = "django-nose" }, { name = "nose-timer" }, @@ -2127,7 +2113,6 @@ test = [ requires-dist = [ { name = "aloe", marker = "extra == 'test'", specifier = "==0.2.0" }, { name = "aloe-django", marker = "extra == 'test'", specifier = "==0.2.0" }, - { name = "aloe-webdriver", marker = "extra == 'test'", specifier = "==0.6.0" }, { name = "aws-xray-sdk", specifier = "==2.9.0" }, { name = "awslambdaric", specifier = "==3.1.1" }, { name = "boto3", specifier = "==1.40.41" }, From b769834bdd969a80bbfcf70f042a3b730c7131c9 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 09:25:42 +1000 Subject: [PATCH 22/34] Silence error logs during tests --- rdrf/rdrf/settings_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rdrf/rdrf/settings_test.py b/rdrf/rdrf/settings_test.py index 31ea192db..67d5ffae1 100644 --- a/rdrf/rdrf/settings_test.py +++ b/rdrf/rdrf/settings_test.py @@ -1,5 +1,5 @@ from .settings import * # noqa -from .settings import INSTALLED_APPS +from .settings import INSTALLED_APPS, LOGGING INSTALLED_APPS += [ "aloe_django", @@ -16,3 +16,6 @@ "rdrf.testing.behaviour.features.runner.GherkinNoDjangoTestDBTestRunner" ) GHERKIN_TEST_CLASS = "aloe.testclass.TestCase" + +# Remove verbose error handler from root logger during tests +LOGGING["loggers"][""]["handlers"] = ["console"] From 0b90095e2b47c524ca69e95a74fb7c0f92e0e2ae Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 09:26:02 +1000 Subject: [PATCH 23/34] Allow testing a single feature --- scripts/end2end-tests.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/end2end-tests.sh b/scripts/end2end-tests.sh index b03897cdd..6606084f3 100755 --- a/scripts/end2end-tests.sh +++ b/scripts/end2end-tests.sh @@ -7,11 +7,15 @@ elif [ "${1}" != "dev" ] && [ "${1}" != "prod" ]; then echo "You probably want one of these:" echo "> $0 dev" echo "> $0 prod" + echo "> $0 dev features/base_login.feature" exit 1 else STACK=${1} fi +# optional feature file argument +FEATURE=${2:-} + alias aloe='docker compose -f docker-compose-aloe.yml' alias selenium='docker compose -f docker-compose-selenium.yml' alias teststack="docker compose -f docker-compose-teststack-base.yml -f docker-compose-teststack-${STACK}.yml" @@ -40,7 +44,11 @@ aloe stop aloe rm --force set +e -aloe run --rm aloe_${STACK} +if [ -n "$FEATURE" ]; then + aloe run --rm aloe_${STACK} aloe "$FEATURE" +else + aloe run --rm aloe_${STACK} +fi rval=$? set -e From 7da86bf63b7eb03f6a97ec338087fdc79a82e702 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 09:34:12 +1000 Subject: [PATCH 24/34] Fix lint issue --- rdrf/rdrf/testing/behaviour/features/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdrf/rdrf/testing/behaviour/features/utils.py b/rdrf/rdrf/testing/behaviour/features/utils.py index 5b43642e5..c8518f856 100644 --- a/rdrf/rdrf/testing/behaviour/features/utils.py +++ b/rdrf/rdrf/testing/behaviour/features/utils.py @@ -3,8 +3,8 @@ import subprocess from aloe import world -from selenium.webdriver.common.by import By from selenium.common.exceptions import StaleElementReferenceException +from selenium.webdriver.common.by import By TEST_WAIT = int(os.environ.get("TEST_WAIT") or "10") From 93eaf817031f5a3008b40439dc21a9b13ddf2695 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 10:31:38 +1000 Subject: [PATCH 25/34] Exclude nose dependency --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index f3233b57a..1e14cb28c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,6 +85,9 @@ test = [ [tool.uv.sources] openapi-client = { path = "./clients/xnat/generated" } +[tool.uv] +exclude-dependencies = ["nose"] + [tool.hatch.metadata] allow-direct-references = true From 89498d928e481d233e5746492259685cbe346a52 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 10:32:11 +1000 Subject: [PATCH 26/34] Upgrade pycountry and aws-xray-sdk --- pyproject.toml | 4 ++-- uv.lock | 56 +++++++++++--------------------------------------- 2 files changed, 14 insertions(+), 46 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1e14cb28c..23aa2836c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ dependencies = [ "jsonschema==4.4.0", "openpyxl==3.0.9", "psycopg2-binary==2.9.10", - "pycountry==22.1.10", + "pycountry==24.6.1", "python-dateutil==2.8.2", "python-magic==0.4.24", "pyyaml==6.0.3", @@ -42,7 +42,7 @@ dependencies = [ "django-simple-history==3.11.0", "lark==1.0.0", "boto3==1.40.41", - "aws-xray-sdk==2.9.0", + "aws-xray-sdk==2.15.0", "graphene-django==3.2.3", "django-filter==25.1", "flatten_json==0.1.13", diff --git a/uv.lock b/uv.lock index 95ef8fc62..ca8a3712d 100644 --- a/uv.lock +++ b/uv.lock @@ -2,6 +2,9 @@ version = 1 revision = 3 requires-python = ">=3.13" +[manifest] +excludes = ["nose"] + [[package]] name = "alabaster" version = "1.0.0" @@ -19,7 +22,6 @@ dependencies = [ { name = "ansicolors" }, { name = "colorama" }, { name = "gherkin-official" }, - { name = "nose" }, ] sdist = { url = "https://files.pythonhosted.org/packages/d6/43/f64222832386b8dc31078086aa157ba67581275630974a204f3df52da56e/aloe-0.2.0.tar.gz", hash = "sha256:d73f69d933600f3ba20c6773df485cc42b5b2e8c274fa3f6798750aedbaf5aa2", size = 97193, upload-time = "2020-01-12T04:58:52.558Z" } @@ -101,16 +103,15 @@ wheels = [ [[package]] name = "aws-xray-sdk" -version = "2.9.0" +version = "2.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, - { name = "future" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/49/26/927206007f1ac57b0801046dc9baed8df9ccbdc7622b79bdaf0c193e8051/aws-xray-sdk-2.9.0.tar.gz", hash = "sha256:b0cd972db218d4d8f7b53ad806fc6184626b924c4997ae58fc9f2a8cd1281568", size = 71968, upload-time = "2021-12-06T20:55:24.897Z" } +sdist = { url = "https://files.pythonhosted.org/packages/14/25/0cbd7a440080def5e6f063720c3b190a25f8aa2938c1e34415dc18241596/aws_xray_sdk-2.15.0.tar.gz", hash = "sha256:794381b96e835314345068ae1dd3b9120bd8b4e21295066c37e8814dbb341365", size = 76315, upload-time = "2025-10-29T20:59:45Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/52/4b/4e0b47146a3fdca48b00774b7280e35c48c48aa9960010c6fc4a3f7f49ad/aws_xray_sdk-2.9.0-py2.py3-none-any.whl", hash = "sha256:98216b3ac8281b51b59a8703f8ec561c460807d9d0679838f5c0179d381d7e58", size = 98902, upload-time = "2021-12-06T20:56:12.011Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c3/f30a7a63e664acc7c2545ca0491b6ce8264536e0e5cad3965f1d1b91e960/aws_xray_sdk-2.15.0-py2.py3-none-any.whl", hash = "sha256:422d62ad7d52e373eebb90b642eb1bb24657afe03b22a8df4a8b2e5108e278a3", size = 103228, upload-time = "2025-10-29T21:00:24.12Z" }, ] [[package]] @@ -400,9 +401,6 @@ wheels = [ name = "django-nose" version = "1.4.7" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "nose" }, -] sdist = { url = "https://files.pythonhosted.org/packages/4c/d6/a340da9854cf0a2b54e23cf9147911b1e15a831911428983dd0158572ce9/django-nose-1.4.7.tar.gz", hash = "sha256:a4885cd002d65fd2de96e2bb2563ef477c3fbe207009360c015fca5c3b5561b7", size = 45041, upload-time = "2020-08-20T02:49:43.355Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a5/5e/804eda7b128162d215de14c0572717f16508cbdb899d4e839f51cef5481e/django_nose-1.4.7-py2.py3-none-any.whl", hash = "sha256:304adc447ee35b889b733d7106004f98aa401d8387ddcada5d4f2239d86790a9", size = 26470, upload-time = "2020-08-20T02:49:13.44Z" }, @@ -593,15 +591,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/dd/174c3a6bbc66913d8d95f259026b93595e4944bde47dc3a60309acd0a36b/flatten_json-0.1.13-py3-none-any.whl", hash = "sha256:2998c8b7d2ba4b4073589ee1c460049bcb45cdf559ba1c738a38cd48a8e48d19", size = 7961, upload-time = "2023-10-27T17:16:41.774Z" }, ] -[[package]] -name = "future" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490, upload-time = "2024-02-21T11:52:38.461Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326, upload-time = "2024-02-21T11:52:35.956Z" }, -] - [[package]] name = "gherkin-official" version = "4.1.3" @@ -1059,22 +1048,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bd/d9/617e6af809bf3a1d468e0d58c3997b1dc219a9a9202e650d30c2fc85d481/mock-5.2.0-py3-none-any.whl", hash = "sha256:7ba87f72ca0e915175596069dbbcc7c75af7b5e9b9bc107ad6349ede0819982f", size = 31617, upload-time = "2025-03-03T12:31:41.518Z" }, ] -[[package]] -name = "nose" -version = "1.3.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/58/a5/0dc93c3ec33f4e281849523a5a913fa1eea9a3068acfa754d44d88107a44/nose-1.3.7.tar.gz", hash = "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98", size = 280488, upload-time = "2015-06-02T09:12:32.961Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/15/d8/dd071918c040f50fa1cf80da16423af51ff8ce4a0f2399b7bf8de45ac3d9/nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", size = 154731, upload-time = "2015-06-02T09:12:40.57Z" }, -] - [[package]] name = "nose-timer" version = "0.7.5" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "nose" }, -] sdist = { url = "https://files.pythonhosted.org/packages/81/61/6476ed1c7a7bbb114246bb4632ec3a72008bc2d25cfbf3f4b1962143371f/nose-timer-0.7.5.tar.gz", hash = "sha256:647eeac86359188ecf02c75b0ab49d20ad10c41814ee89af30fcaf8d109b9f17", size = 7742, upload-time = "2019-03-14T04:56:36.485Z" } [[package]] @@ -1327,12 +1304,12 @@ wheels = [ [[package]] name = "pycountry" -version = "22.1.10" +version = "24.6.1" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "setuptools" }, +sdist = { url = "https://files.pythonhosted.org/packages/76/57/c389fa68c50590881a75b7883eeb3dc15e9e73a0fdc001cdd45c13290c92/pycountry-24.6.1.tar.gz", hash = "sha256:b61b3faccea67f87d10c1f2b0fc0be714409e8fcdcc1315613174f6466c10221", size = 6043910, upload-time = "2024-06-01T04:12:15.05Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/ec/1fb891d8a2660716aadb2143235481d15ed1cbfe3ad669194690b0604492/pycountry-24.6.1-py3-none-any.whl", hash = "sha256:f1a4fb391cd7214f8eefd39556d740adcc233c778a27f8942c8dca351d6ce06f", size = 6335189, upload-time = "2024-06-01T04:11:49.711Z" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/03/c4/2db520ae518156a88b419b2865d4fdc85fe78573948358f79dbaf0cf2b30/pycountry-22.1.10.tar.gz", hash = "sha256:b9a6d9cdbf53f81ccdf73f6f5de01b0d8493cab2213a230af3e34458de85ea32", size = 10060795, upload-time = "2022-01-10T07:40:43.133Z" } [[package]] name = "pycparser" @@ -1721,15 +1698,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/58/d0/55a6b7c6f35aad4c8a54be0eb7a52c1ff29a59542fc3e655f0ecbb14456d/selenium-4.39.0-py3-none-any.whl", hash = "sha256:c85f65d5610642ca0f47dae9d5cc117cd9e831f74038bc09fe1af126288200f9", size = 9655249, upload-time = "2025-12-06T23:12:33.085Z" }, ] -[[package]] -name = "setuptools" -version = "80.9.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, -] - [[package]] name = "simplejson" version = "3.20.2" @@ -2113,7 +2081,7 @@ test = [ requires-dist = [ { name = "aloe", marker = "extra == 'test'", specifier = "==0.2.0" }, { name = "aloe-django", marker = "extra == 'test'", specifier = "==0.2.0" }, - { name = "aws-xray-sdk", specifier = "==2.9.0" }, + { name = "aws-xray-sdk", specifier = "==2.15.0" }, { name = "awslambdaric", specifier = "==3.1.1" }, { name = "boto3", specifier = "==1.40.41" }, { name = "ccg-django-utils", specifier = "==0.4.2" }, @@ -2151,7 +2119,7 @@ requires-dist = [ { name = "phonenumberslite", specifier = "==8.12.39" }, { name = "pillow", specifier = "==11.3.0" }, { name = "psycopg2-binary", specifier = "==2.9.10" }, - { name = "pycountry", specifier = "==22.1.10" }, + { name = "pycountry", specifier = "==24.6.1" }, { name = "pynose", marker = "extra == 'test'", specifier = "==1.5.5" }, { name = "pytest", marker = "extra == 'test'", specifier = "==7.1.1" }, { name = "pytest-django", marker = "extra == 'test'", specifier = "==4.5.2" }, From ea991a24577089293f239d14ab6570e62b6d2294 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 10:32:58 +1000 Subject: [PATCH 27/34] Remove extra printing in e2e tests --- rdrf/rdrf/testing/behaviour/features/steps.py | 6 ----- rdrf/rdrf/testing/behaviour/features/utils.py | 26 +++++++------------ 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/rdrf/rdrf/testing/behaviour/features/steps.py b/rdrf/rdrf/testing/behaviour/features/steps.py index a7d06596a..690d1008e 100644 --- a/rdrf/rdrf/testing/behaviour/features/steps.py +++ b/rdrf/rdrf/testing/behaviour/features/steps.py @@ -232,9 +232,6 @@ def correct_item(input_element): if not correct_item(input_element): continue input_element.send_keys(cde_value) - input_id = input_element.get_attribute("id") - print("input id %s sent keys '%s'" % (input_id, cde_value)) - return except BaseException: pass @@ -765,7 +762,6 @@ def scroll_to_section(step, section): from selenium.webdriver.common.action_chains import ActionChains mover = ActionChains(world.browser) - print("scrolling to section %s" % section) section_xpath = ( ".//div[@class='panel panel-default' and contains(.,'%s') and not(contains(., '__prefix__')) and not(contains(.,'View previous values'))]" % section @@ -775,9 +771,7 @@ def scroll_to_section(step, section): ) if not section_element: raise Exception("could not find section %s" % section) - y = utils.scroll_to(section_element) mover.move_to_element(section_element) - print("scrolled to section %s y = %s" % (section, y)) @step('I click the add button for multisection "(.*)"') diff --git a/rdrf/rdrf/testing/behaviour/features/utils.py b/rdrf/rdrf/testing/behaviour/features/utils.py index c8518f856..ff6babf30 100644 --- a/rdrf/rdrf/testing/behaviour/features/utils.py +++ b/rdrf/rdrf/testing/behaviour/features/utils.py @@ -251,13 +251,7 @@ def scroll_to(element): def scroll_to_multisection_cde(section, cde, item=1): - # item 1 means the 1st block of cdes in the multisection - print( - "Attempting to scroll to section %s cde %s item %s" - % (section, cde, item) - ) formset_string = "-%s-" % (int(item) - 1) - print("formset_string = %s" % formset_string) xpath = "//div[@class='card-header' and contains(., '%s')]" % section panel_heading = world.browser.find_element( by=By.XPATH, value=xpath @@ -274,7 +268,6 @@ def scroll_to_multisection_cde(section, cde, item=1): for label_element in default_panel.find_elements( by=By.XPATH, value=label_expression ): - print("found a label element for cde %s" % cde) input_div = label_element.find_element( by=By.XPATH, value=".//following-sibling::div" ) @@ -286,10 +279,6 @@ def scroll_to_multisection_cde(section, cde, item=1): % formset_string, ) scroll_to(input_element) - print( - "found input element: id = %s" - % input_element.get_attribute("id") - ) return input_element except BaseException: continue @@ -376,8 +365,10 @@ def wait_for_first_section(): ) ) + # From aloe_webdriver: https://github.com/aloetesting/aloe_webdriver + def string_literal(content): if '"' in content and "'" in content: raise ValueError("Cannot represent this string in XPath") @@ -389,12 +380,15 @@ def string_literal(content): return content -def contains_content(content): - for elem in world.browser.find_elements(By.XPATH, - '//*[contains(normalize-space(.), {content}) ' - 'and not(./*[contains(normalize-space(.), {content})])]' - .format(content=string_literal(content))): +def contains_content(content): + for elem in world.browser.find_elements( + By.XPATH, + "//*[contains(normalize-space(.), {content}) " + "and not(./*[contains(normalize-space(.), {content})])]".format( + content=string_literal(content) + ), + ): try: if elem.is_displayed(): return True From a39aecd7ab450cf78e4270577f4cc6f37fc6d122 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 10:39:46 +1000 Subject: [PATCH 28/34] Update countries and states --- .../patients/migrations/0067_country.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 rdrf/registry/patients/migrations/0067_country.py diff --git a/rdrf/registry/patients/migrations/0067_country.py b/rdrf/registry/patients/migrations/0067_country.py new file mode 100644 index 000000000..d0f50f05f --- /dev/null +++ b/rdrf/registry/patients/migrations/0067_country.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.1 on 2026-01-16 00:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('patients', '0066_history_date'), + ] + + operations = [ + migrations.AlterField( + model_name='historicalpatientrelative', + name='location', + field=models.CharField(choices=[('AU - WA', 'Australia - WA'), ('AU - SA', 'Australia - SA'), ('AU - NSW', 'Australia - NSW'), ('AU - QLD', 'Australia - QLD'), ('AU - NT', 'Australia - NT'), ('AU - VIC', 'Australia - VIC'), ('AU - TAS', 'Australia - TAS'), ('NZ', 'New Zealand'), ('AF', 'Afghanistan'), ('AL', 'Albania'), ('DZ', 'Algeria'), ('AS', 'American Samoa'), ('AD', 'Andorra'), ('AO', 'Angola'), ('AI', 'Anguilla'), ('AQ', 'Antarctica'), ('AG', 'Antigua and Barbuda'), ('AR', 'Argentina'), ('AM', 'Armenia'), ('AW', 'Aruba'), ('AU', 'Australia'), ('AT', 'Austria'), ('AZ', 'Azerbaijan'), ('BS', 'Bahamas'), ('BH', 'Bahrain'), ('BD', 'Bangladesh'), ('BB', 'Barbados'), ('BY', 'Belarus'), ('BE', 'Belgium'), ('BZ', 'Belize'), ('BJ', 'Benin'), ('BM', 'Bermuda'), ('BT', 'Bhutan'), ('BO', 'Bolivia, Plurinational State of'), ('BQ', 'Bonaire, Sint Eustatius and Saba'), ('BA', 'Bosnia and Herzegovina'), ('BW', 'Botswana'), ('BV', 'Bouvet Island'), ('BR', 'Brazil'), ('IO', 'British Indian Ocean Territory'), ('BN', 'Brunei Darussalam'), ('BG', 'Bulgaria'), ('BF', 'Burkina Faso'), ('BI', 'Burundi'), ('CV', 'Cabo Verde'), ('KH', 'Cambodia'), ('CM', 'Cameroon'), ('CA', 'Canada'), ('KY', 'Cayman Islands'), ('CF', 'Central African Republic'), ('TD', 'Chad'), ('CL', 'Chile'), ('CN', 'China'), ('CX', 'Christmas Island'), ('CC', 'Cocos (Keeling) Islands'), ('CO', 'Colombia'), ('KM', 'Comoros'), ('CG', 'Congo'), ('CD', 'Congo, The Democratic Republic of the'), ('CK', 'Cook Islands'), ('CR', 'Costa Rica'), ('HR', 'Croatia'), ('CU', 'Cuba'), ('CW', 'Curaçao'), ('CY', 'Cyprus'), ('CZ', 'Czechia'), ('CI', "Côte d'Ivoire"), ('DK', 'Denmark'), ('DJ', 'Djibouti'), ('DM', 'Dominica'), ('DO', 'Dominican Republic'), ('EC', 'Ecuador'), ('EG', 'Egypt'), ('SV', 'El Salvador'), ('GQ', 'Equatorial Guinea'), ('ER', 'Eritrea'), ('EE', 'Estonia'), ('SZ', 'Eswatini'), ('ET', 'Ethiopia'), ('FK', 'Falkland Islands (Malvinas)'), ('FO', 'Faroe Islands'), ('FJ', 'Fiji'), ('FI', 'Finland'), ('FR', 'France'), ('GF', 'French Guiana'), ('PF', 'French Polynesia'), ('TF', 'French Southern Territories'), ('GA', 'Gabon'), ('GM', 'Gambia'), ('GE', 'Georgia'), ('DE', 'Germany'), ('GH', 'Ghana'), ('GI', 'Gibraltar'), ('GR', 'Greece'), ('GL', 'Greenland'), ('GD', 'Grenada'), ('GP', 'Guadeloupe'), ('GU', 'Guam'), ('GT', 'Guatemala'), ('GG', 'Guernsey'), ('GN', 'Guinea'), ('GW', 'Guinea-Bissau'), ('GY', 'Guyana'), ('HT', 'Haiti'), ('HM', 'Heard Island and McDonald Islands'), ('VA', 'Holy See (Vatican City State)'), ('HN', 'Honduras'), ('HK', 'Hong Kong'), ('HU', 'Hungary'), ('IS', 'Iceland'), ('IN', 'India'), ('ID', 'Indonesia'), ('IR', 'Iran, Islamic Republic of'), ('IQ', 'Iraq'), ('IE', 'Ireland'), ('IM', 'Isle of Man'), ('IL', 'Israel'), ('IT', 'Italy'), ('JM', 'Jamaica'), ('JP', 'Japan'), ('JE', 'Jersey'), ('JO', 'Jordan'), ('KZ', 'Kazakhstan'), ('KE', 'Kenya'), ('KI', 'Kiribati'), ('KP', "Korea, Democratic People's Republic of"), ('KR', 'Korea, Republic of'), ('KW', 'Kuwait'), ('KG', 'Kyrgyzstan'), ('LA', "Lao People's Democratic Republic"), ('LV', 'Latvia'), ('LB', 'Lebanon'), ('LS', 'Lesotho'), ('LR', 'Liberia'), ('LY', 'Libya'), ('LI', 'Liechtenstein'), ('LT', 'Lithuania'), ('LU', 'Luxembourg'), ('MO', 'Macao'), ('MG', 'Madagascar'), ('MW', 'Malawi'), ('MY', 'Malaysia'), ('MV', 'Maldives'), ('ML', 'Mali'), ('MT', 'Malta'), ('MH', 'Marshall Islands'), ('MQ', 'Martinique'), ('MR', 'Mauritania'), ('MU', 'Mauritius'), ('YT', 'Mayotte'), ('MX', 'Mexico'), ('FM', 'Micronesia, Federated States of'), ('MD', 'Moldova, Republic of'), ('MC', 'Monaco'), ('MN', 'Mongolia'), ('ME', 'Montenegro'), ('MS', 'Montserrat'), ('MA', 'Morocco'), ('MZ', 'Mozambique'), ('MM', 'Myanmar'), ('NA', 'Namibia'), ('NR', 'Nauru'), ('NP', 'Nepal'), ('NL', 'Netherlands'), ('NC', 'New Caledonia'), ('NZ', 'New Zealand'), ('NI', 'Nicaragua'), ('NE', 'Niger'), ('NG', 'Nigeria'), ('NU', 'Niue'), ('NF', 'Norfolk Island'), ('MK', 'North Macedonia'), ('MP', 'Northern Mariana Islands'), ('NO', 'Norway'), ('OM', 'Oman'), ('PK', 'Pakistan'), ('PW', 'Palau'), ('PS', 'Palestine, State of'), ('PA', 'Panama'), ('PG', 'Papua New Guinea'), ('PY', 'Paraguay'), ('PE', 'Peru'), ('PH', 'Philippines'), ('PN', 'Pitcairn'), ('PL', 'Poland'), ('PT', 'Portugal'), ('PR', 'Puerto Rico'), ('QA', 'Qatar'), ('RO', 'Romania'), ('RU', 'Russian Federation'), ('RW', 'Rwanda'), ('RE', 'Réunion'), ('BL', 'Saint Barthélemy'), ('SH', 'Saint Helena, Ascension and Tristan da Cunha'), ('KN', 'Saint Kitts and Nevis'), ('LC', 'Saint Lucia'), ('MF', 'Saint Martin (French part)'), ('PM', 'Saint Pierre and Miquelon'), ('VC', 'Saint Vincent and the Grenadines'), ('WS', 'Samoa'), ('SM', 'San Marino'), ('ST', 'Sao Tome and Principe'), ('SA', 'Saudi Arabia'), ('SN', 'Senegal'), ('RS', 'Serbia'), ('SC', 'Seychelles'), ('SL', 'Sierra Leone'), ('SG', 'Singapore'), ('SX', 'Sint Maarten (Dutch part)'), ('SK', 'Slovakia'), ('SI', 'Slovenia'), ('SB', 'Solomon Islands'), ('SO', 'Somalia'), ('ZA', 'South Africa'), ('GS', 'South Georgia and the South Sandwich Islands'), ('SS', 'South Sudan'), ('ES', 'Spain'), ('LK', 'Sri Lanka'), ('SD', 'Sudan'), ('SR', 'Suriname'), ('SJ', 'Svalbard and Jan Mayen'), ('SE', 'Sweden'), ('CH', 'Switzerland'), ('SY', 'Syrian Arab Republic'), ('TW', 'Taiwan, Province of China'), ('TJ', 'Tajikistan'), ('TZ', 'Tanzania, United Republic of'), ('TH', 'Thailand'), ('TL', 'Timor-Leste'), ('TG', 'Togo'), ('TK', 'Tokelau'), ('TO', 'Tonga'), ('TT', 'Trinidad and Tobago'), ('TN', 'Tunisia'), ('TM', 'Turkmenistan'), ('TC', 'Turks and Caicos Islands'), ('TV', 'Tuvalu'), ('TR', 'Türkiye'), ('UG', 'Uganda'), ('UA', 'Ukraine'), ('AE', 'United Arab Emirates'), ('GB', 'United Kingdom'), ('US', 'United States'), ('UM', 'United States Minor Outlying Islands'), ('UY', 'Uruguay'), ('UZ', 'Uzbekistan'), ('VU', 'Vanuatu'), ('VE', 'Venezuela, Bolivarian Republic of'), ('VN', 'Viet Nam'), ('VG', 'Virgin Islands, British'), ('VI', 'Virgin Islands, U.S.'), ('WF', 'Wallis and Futuna'), ('EH', 'Western Sahara'), ('YE', 'Yemen'), ('ZM', 'Zambia'), ('ZW', 'Zimbabwe'), ('AX', 'Åland Islands')], max_length=80), + ), + migrations.AlterField( + model_name='patientrelative', + name='location', + field=models.CharField(choices=[('AU - WA', 'Australia - WA'), ('AU - SA', 'Australia - SA'), ('AU - NSW', 'Australia - NSW'), ('AU - QLD', 'Australia - QLD'), ('AU - NT', 'Australia - NT'), ('AU - VIC', 'Australia - VIC'), ('AU - TAS', 'Australia - TAS'), ('NZ', 'New Zealand'), ('AF', 'Afghanistan'), ('AL', 'Albania'), ('DZ', 'Algeria'), ('AS', 'American Samoa'), ('AD', 'Andorra'), ('AO', 'Angola'), ('AI', 'Anguilla'), ('AQ', 'Antarctica'), ('AG', 'Antigua and Barbuda'), ('AR', 'Argentina'), ('AM', 'Armenia'), ('AW', 'Aruba'), ('AU', 'Australia'), ('AT', 'Austria'), ('AZ', 'Azerbaijan'), ('BS', 'Bahamas'), ('BH', 'Bahrain'), ('BD', 'Bangladesh'), ('BB', 'Barbados'), ('BY', 'Belarus'), ('BE', 'Belgium'), ('BZ', 'Belize'), ('BJ', 'Benin'), ('BM', 'Bermuda'), ('BT', 'Bhutan'), ('BO', 'Bolivia, Plurinational State of'), ('BQ', 'Bonaire, Sint Eustatius and Saba'), ('BA', 'Bosnia and Herzegovina'), ('BW', 'Botswana'), ('BV', 'Bouvet Island'), ('BR', 'Brazil'), ('IO', 'British Indian Ocean Territory'), ('BN', 'Brunei Darussalam'), ('BG', 'Bulgaria'), ('BF', 'Burkina Faso'), ('BI', 'Burundi'), ('CV', 'Cabo Verde'), ('KH', 'Cambodia'), ('CM', 'Cameroon'), ('CA', 'Canada'), ('KY', 'Cayman Islands'), ('CF', 'Central African Republic'), ('TD', 'Chad'), ('CL', 'Chile'), ('CN', 'China'), ('CX', 'Christmas Island'), ('CC', 'Cocos (Keeling) Islands'), ('CO', 'Colombia'), ('KM', 'Comoros'), ('CG', 'Congo'), ('CD', 'Congo, The Democratic Republic of the'), ('CK', 'Cook Islands'), ('CR', 'Costa Rica'), ('HR', 'Croatia'), ('CU', 'Cuba'), ('CW', 'Curaçao'), ('CY', 'Cyprus'), ('CZ', 'Czechia'), ('CI', "Côte d'Ivoire"), ('DK', 'Denmark'), ('DJ', 'Djibouti'), ('DM', 'Dominica'), ('DO', 'Dominican Republic'), ('EC', 'Ecuador'), ('EG', 'Egypt'), ('SV', 'El Salvador'), ('GQ', 'Equatorial Guinea'), ('ER', 'Eritrea'), ('EE', 'Estonia'), ('SZ', 'Eswatini'), ('ET', 'Ethiopia'), ('FK', 'Falkland Islands (Malvinas)'), ('FO', 'Faroe Islands'), ('FJ', 'Fiji'), ('FI', 'Finland'), ('FR', 'France'), ('GF', 'French Guiana'), ('PF', 'French Polynesia'), ('TF', 'French Southern Territories'), ('GA', 'Gabon'), ('GM', 'Gambia'), ('GE', 'Georgia'), ('DE', 'Germany'), ('GH', 'Ghana'), ('GI', 'Gibraltar'), ('GR', 'Greece'), ('GL', 'Greenland'), ('GD', 'Grenada'), ('GP', 'Guadeloupe'), ('GU', 'Guam'), ('GT', 'Guatemala'), ('GG', 'Guernsey'), ('GN', 'Guinea'), ('GW', 'Guinea-Bissau'), ('GY', 'Guyana'), ('HT', 'Haiti'), ('HM', 'Heard Island and McDonald Islands'), ('VA', 'Holy See (Vatican City State)'), ('HN', 'Honduras'), ('HK', 'Hong Kong'), ('HU', 'Hungary'), ('IS', 'Iceland'), ('IN', 'India'), ('ID', 'Indonesia'), ('IR', 'Iran, Islamic Republic of'), ('IQ', 'Iraq'), ('IE', 'Ireland'), ('IM', 'Isle of Man'), ('IL', 'Israel'), ('IT', 'Italy'), ('JM', 'Jamaica'), ('JP', 'Japan'), ('JE', 'Jersey'), ('JO', 'Jordan'), ('KZ', 'Kazakhstan'), ('KE', 'Kenya'), ('KI', 'Kiribati'), ('KP', "Korea, Democratic People's Republic of"), ('KR', 'Korea, Republic of'), ('KW', 'Kuwait'), ('KG', 'Kyrgyzstan'), ('LA', "Lao People's Democratic Republic"), ('LV', 'Latvia'), ('LB', 'Lebanon'), ('LS', 'Lesotho'), ('LR', 'Liberia'), ('LY', 'Libya'), ('LI', 'Liechtenstein'), ('LT', 'Lithuania'), ('LU', 'Luxembourg'), ('MO', 'Macao'), ('MG', 'Madagascar'), ('MW', 'Malawi'), ('MY', 'Malaysia'), ('MV', 'Maldives'), ('ML', 'Mali'), ('MT', 'Malta'), ('MH', 'Marshall Islands'), ('MQ', 'Martinique'), ('MR', 'Mauritania'), ('MU', 'Mauritius'), ('YT', 'Mayotte'), ('MX', 'Mexico'), ('FM', 'Micronesia, Federated States of'), ('MD', 'Moldova, Republic of'), ('MC', 'Monaco'), ('MN', 'Mongolia'), ('ME', 'Montenegro'), ('MS', 'Montserrat'), ('MA', 'Morocco'), ('MZ', 'Mozambique'), ('MM', 'Myanmar'), ('NA', 'Namibia'), ('NR', 'Nauru'), ('NP', 'Nepal'), ('NL', 'Netherlands'), ('NC', 'New Caledonia'), ('NZ', 'New Zealand'), ('NI', 'Nicaragua'), ('NE', 'Niger'), ('NG', 'Nigeria'), ('NU', 'Niue'), ('NF', 'Norfolk Island'), ('MK', 'North Macedonia'), ('MP', 'Northern Mariana Islands'), ('NO', 'Norway'), ('OM', 'Oman'), ('PK', 'Pakistan'), ('PW', 'Palau'), ('PS', 'Palestine, State of'), ('PA', 'Panama'), ('PG', 'Papua New Guinea'), ('PY', 'Paraguay'), ('PE', 'Peru'), ('PH', 'Philippines'), ('PN', 'Pitcairn'), ('PL', 'Poland'), ('PT', 'Portugal'), ('PR', 'Puerto Rico'), ('QA', 'Qatar'), ('RO', 'Romania'), ('RU', 'Russian Federation'), ('RW', 'Rwanda'), ('RE', 'Réunion'), ('BL', 'Saint Barthélemy'), ('SH', 'Saint Helena, Ascension and Tristan da Cunha'), ('KN', 'Saint Kitts and Nevis'), ('LC', 'Saint Lucia'), ('MF', 'Saint Martin (French part)'), ('PM', 'Saint Pierre and Miquelon'), ('VC', 'Saint Vincent and the Grenadines'), ('WS', 'Samoa'), ('SM', 'San Marino'), ('ST', 'Sao Tome and Principe'), ('SA', 'Saudi Arabia'), ('SN', 'Senegal'), ('RS', 'Serbia'), ('SC', 'Seychelles'), ('SL', 'Sierra Leone'), ('SG', 'Singapore'), ('SX', 'Sint Maarten (Dutch part)'), ('SK', 'Slovakia'), ('SI', 'Slovenia'), ('SB', 'Solomon Islands'), ('SO', 'Somalia'), ('ZA', 'South Africa'), ('GS', 'South Georgia and the South Sandwich Islands'), ('SS', 'South Sudan'), ('ES', 'Spain'), ('LK', 'Sri Lanka'), ('SD', 'Sudan'), ('SR', 'Suriname'), ('SJ', 'Svalbard and Jan Mayen'), ('SE', 'Sweden'), ('CH', 'Switzerland'), ('SY', 'Syrian Arab Republic'), ('TW', 'Taiwan, Province of China'), ('TJ', 'Tajikistan'), ('TZ', 'Tanzania, United Republic of'), ('TH', 'Thailand'), ('TL', 'Timor-Leste'), ('TG', 'Togo'), ('TK', 'Tokelau'), ('TO', 'Tonga'), ('TT', 'Trinidad and Tobago'), ('TN', 'Tunisia'), ('TM', 'Turkmenistan'), ('TC', 'Turks and Caicos Islands'), ('TV', 'Tuvalu'), ('TR', 'Türkiye'), ('UG', 'Uganda'), ('UA', 'Ukraine'), ('AE', 'United Arab Emirates'), ('GB', 'United Kingdom'), ('US', 'United States'), ('UM', 'United States Minor Outlying Islands'), ('UY', 'Uruguay'), ('UZ', 'Uzbekistan'), ('VU', 'Vanuatu'), ('VE', 'Venezuela, Bolivarian Republic of'), ('VN', 'Viet Nam'), ('VG', 'Virgin Islands, British'), ('VI', 'Virgin Islands, U.S.'), ('WF', 'Wallis and Futuna'), ('EH', 'Western Sahara'), ('YE', 'Yemen'), ('ZM', 'Zambia'), ('ZW', 'Zimbabwe'), ('AX', 'Åland Islands')], max_length=80), + ), + ] From f7a841ba3ccbd48da6af596c512d214f74aecdcb Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 10:52:24 +1000 Subject: [PATCH 29/34] Update test zips --- .../behaviour/features/exported_data/ang.zip | Bin 60409 -> 60460 bytes .../behaviour/features/exported_data/dd.zip | Bin 23050 -> 23055 bytes .../behaviour/features/exported_data/fh.zip | Bin 39014 -> 38934 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/rdrf/rdrf/testing/behaviour/features/exported_data/ang.zip b/rdrf/rdrf/testing/behaviour/features/exported_data/ang.zip index c710f6c74ddceb312d578482c6304e033ec4edc1..fc0f0d9561b876e728509da92e4f282b508457b5 100644 GIT binary patch delta 27491 zcmZs?QnsrckC0S4~G@$=ELNu5X;R!*5|ACS8Kd3W+{!cKB{y(&`0{(e=RlY2629Q8N zfowoPQ2%Z-cCciW7grPB$TDJW1j`S&o3VSJ9*B|I4?37!tQT?K@);-a zcgbX$cZ)*u4o8zhA4WY*^fuK&E(gy_<8r(@T{K!*^(FOpC&qpM2@NtOhO8JJU;h@ZOSkV`4aNfFxO*$1IcCicM?M|qNJb<&goCFl=w{A&y~ zxxY+kUxgmQv-!rlLc8)s`zLOE}$T>{m{DOTyHJ*mj1TNwgwQ)fyN1Mjx{jcGN`vT&hwz z`@4<7JZGd*vmhIRaYjE1#}WiG(@KJ0kqQpJaYqUXK+0zdbzfQ!&Y_Y!IsCMC!uVob zN2;q{>tGM=AaKIN@OzsG?@aq%=|fLxOlo)Pibc`vv*w7cjijO1&o|4wkO<%gU4dYOdW)GBx(|-eih6?*>cH>IKC#{aU_v z^O9i)K-pa4Ljl>YtxnBH*Vo_4U}T?Tw{^g2O9fGQ4_-MhZ9O?*J*^bxHN$(jm5aAp zwb|x1rC9-jo%kD+V;eX_F{lVenvfXR6@nR$sVtR^BOAw`pv0_6+Jy7IJ@RpsqKi8r ztc8aN9l=4OST-CwL5T?p+7uf27oOD#sxT7~00|7w8(3M7xj=CS1;1&b7hA`=T?Iev zOWI73TTd#a(s+@AlP+`=xEurru3KoZ|G|7dr{rEg;E!M6AP!hi1G_|&aS0NbK%&Gt z@-JqIpXf+^WKu`F>=|4D5Ber?N~*X3U3Y@d^-FHW2Ma4Sbydzps6`%~KpBP>94Tjo+9BEP z0Sv#Gerb<8rX?2%aR}J>8U=!>ARRHT86TU$*viL1#q=uLDyL21pbq#;iLPym;7 z52gmJ3Iu@#F2+>Sd2j1Ka`ix`?Vmn;#k5z+ zbh==VB0e#ueb2_QW`WM`CwKC|_?ySs(s+Nld{^}~9MOMv>lYV5vhYd|P=l_+{wtqF zcWo%lR%Ek<(9=!}ubT7l&Z_j?CjDe$wC7Q%`GBca17GD_r*?91ccmD=_}9`ru&8!j zu@-r+nFLs%@HnzMLH!%l`Mp#Yu%TMgL}gKo0{z4)OZPwaFmp*0t$! zOq{t>!7MLl{v{sy>CF>W<=2xqaFvM>LpgHhKwzhkO+87ri`n=Q;olF{uryOUQ=Xk| zvzt_|dRZV%g{~`;KIpZ32jB8&{D@?io-G&-50G}AQ%;f%X5e~$K+_;AJwIcRdGS@* z^N%KP7aY8|WM%owj&W}9>{a(_>e{a$+5olu*l7iy9-a{G`gfQUlmYdR*rtJ}OSs_b zRz^l-y*Kzx(^o1on9JYeCdHPin_p zC^wUAmtH244c~bpKz2a-=)D7`d_*VpYiFuYW$EgtiIIQ)aUt}HD%e(o8m{JcLm!sG zNa7T#NOr-RYs$k<|4WPf`^17JyP{B|rU%IM$Ks2iiO(v9QAgI{!Z<=f&2*l}$Dfs_ z*bg>uhq@cpi%*Bao$ic+dfoCBE=whxluKQ@hjI4TCYW|GyJyGB7lH@;p59|0lz@5+*0?fF)x`p^^k8Mm;~r{(OIUhWfFhBDnUw<@p`)e!serS+E{(vlUF6vz~(QpVoB9*3W9_ay}^7yZUpZ;Vdh z{4OaYIsJ(uM$5;kIfe&{0kqybku`b$Z?T;ObAeNX-7&rI>!u%=j=7xaZ&w_!>6gVE z#&%X?VHZahLRkzjr~K7Acd;GibCqsL!5_`>PxFEFi}*J?hR;9{Jd&{eqrRWpKLE

    K~v0`2`O)WNY!XW*1D z2G+o`gg9Vcd`2VGQ_Mok#9d18bigubbFhVGOitUa4j~U`?m+pK0zfG)ZZ)BcPYY*0 zp~(~mGLwJNshts(e9Z)S9!&ZWD#1!}kP^W&jyA6#F7TJ$cd5{G4OeUVy1_uHdgztL z+4t?yjC{GTdR#rMU$d$Q#X;e3Mpc1hCkroGzP>x|cyIxvb_o_U)%RiXbHG$z!m8OJ zE4A=#iNJTB9QDft-mRMqC=HOEKsv;RI*dj&a}VF@d(hme6A(0x-k`gHq2=Gf4J0%N zApC4sXg(>BD$bhnUSKJ2y5$0|J#V^D-2rRf!+K((&T<4ye=ncn0$?v2c`X2$9s^lA zW{v_M@j;e+h09?orCAWo9{|bkzpHbVhJd$lGPgmfnuvfzp4=$42azxj)h48MjhQNJ z`L^i}%i?*-j=R|i5_+%Kh`_9)qdC9!JX98Ne5n}FQ)_Z4W_FMwJnXeAIjl{yVu&{| zF`xcylErXeUAuX0EPL7%zDcs}t-$!s%M71yX2{iC#@;*Z?;f7NRsb;}7aKS9U<8~Q7&#G={L7^G2*h-#) zmTMF(n2=(Vmfz_6z$w5=;1-X@lk0mi#I0#_vl!Ew?+Blaok@5C1P{o&0SP#hx>74) zmeE#{#ptcldqhGt<>&oG%bwWThECX_-w8gX77b(b4}7B6a)5=V2+O!(_-6Rl(7AD| zN&RrS3sluSlG0xpPAPL@@S9B}Zm~7GU^lSBnnY}V&U2#0}81FTN%vQq9j7VQ(7I>LHfvV?8%#yn-Y;!v{6#P6GmhX^GqpUbY z;3#{Hs4+6ue*m~*`5D(y@w>&87zU#IOJWaSRcl>=fK0@u4#uzs#0Iv(aVk7xq5!N) z4B0P@x@EclD^#I<(UoZo?DYOCf?M)(^Z9Fxg z4a&;sF@NaF{Mgi|D55BmO$2_41K}Aa#<#M=-iYMEgJf^L&Q%}X;Pr+p!e40GR!0RT z=xaRR9cY(dFJCwHEd>E56a^Yej26b1u{di9bd zhPZ+L78UNK3mbfa!{WH>O9pE;xiM$Tc=GJw+yYS7-BE-F7u-*XRUi=xAtWTbcmF~u zxL`;W$29sC+WOSnQ$OX)vdGdA#l&YE_$f}$NQi@OOHX@M^ER>B`BJ`-2RqlP>U@arf} zGx*PdKkkN{DyBIPhUP5Uz6(2l218Z~tbENV^3W6%$A`mxSyU!bw|l8U<-7--9}Tjg zx54fDh{MxE-=a$Nf}ubbSa^c2biQyspnAMEtmE7ob(C+)(bA={MbOiM`ke|3xMjbP zcF_^$PAT58=-PkqxB=|ffe+ER zb0s5OC_5u5_`5@A&<-!nrk`WDjnK+rem~o=gyju=M&4<4@=Rw?<{De<@#OFuT)pVI zcLPPofimZ_p0%#wV*kxbeBCIy&>!bOE`LSJ z5_ER~dmlWHo)u`Ml8V!-)d8-(teIIRrI!nAs8OszH0rL~>IdIZ*{9I@Bi|}S>~}Mr zsh6A+<(%eH9J1!JflWAiZl8qN=NaaBa!#Dn81ZGUd$B%@V-+6YWV^;I`F&@i>&{b} zqk5MV9-$xRC8vHybBOZt42o{kD*-K5}gGk;yoYf=3D%yEI=^g2Wo;wtoq6)dyim+7)*aS3Zh-a*Wt@Z za^y(+%#YL4USs^_Tpw36vQ-89--Rx_vT)o(Vdvnb^O9U|Mhv-;8>HuxI<|w#Lmci< zKV8qG!9QaK9#H9^jsPGIIGr8tT#j;*cuk{0Dw7)lAYCTQ}$0P#dd7ey&Ue6X-snJ4|YDZ*JDP@+7k0vaiJ zE!~auCyRFgfDUr5TpedGgBi0V^#!~XGD?=`nc8!|yT6}aJ@>QdQ2@04ulITzBnibM zaUHQu1eFa?1fb}5{l{uJBI72T%OPk{6-SJoX*~q%^1IAcvxvXi931f^q&>aS6;#jm z`J>#8PDp!WLe5+Wpa6npNqMht)l2?h9Nq6v!S;rz zM-kQArA>#hvmf;G3y%E`PwjJ9O}TmfCBxa%pbTu6v$_EiVal{gKIg`uK#y5_9zw?7 z7mnao)W?MoC&e*o@WnSa?D;PaJUs#Bh6AhAGB**igxH*s6q3dBfTAFm4QpGe*^aTe z*tcEVZNRlIamUBSSb8 zjWde3kw#dfgQs$%wrpAvuzQCr|JRrvQ|$*jRrR>Sl!W7MNv~S+yL`;*bz&s1XUr1 zsh57jr+LS42q$B}z)VSzZWpOa0Til}2QMy0K_fUFVyh?eUk_(1(;ljTmK6bLXNV|@ zd9jQw3(43jrZ5{u7D%g@I~VtH zd}~Tv?zJRkIs-wKs~I@X5X9Nx?ry6P zz-h{2GjSFL_Y0B~wN;NkRg30b?trCUwhHMvnU5Z`p5O5(hSqoe zblvN}R(Isrt*B#MDxi=ec@b=mwYJT$udNZh9i{2Z!U1dR&$Sw+7hJ0ZY%^!gMUDz` z93hSTYBEdxY$5;6tv{O#FfCUOjH>_Ppk%Id?VHl>+>}`x5OiJvn3=3-5j;xhuPCH$ zVfBSXtHHP{w#b)YNv@zcQX?R*ai_YyNL$3Jz{0IObBg_I+>L~8V<0yl zVz2H}HT8|u7yNtxU(^%6jJ3IH578UAEDcI&YjDNDrlKBVbB6hBRi|MC#kp06WAUs{ zqaYb$cIrOLcRnZgMqXoZu__wbS^z_NY<64F;}WO*4A$yH0)>xI+UeeCn*Ef1W1@rB z9J{uGb%*xfy~pYO7<{eVkWJ#RQv};osCkPH8(vDwFAyn!;{+z6BU%Lp$9bXF``@cB(;Qy~cl#tE7ad*{jR zy2Ek-y(83-c5oOT67I$FgIG-f zB;EorG(RJ~^^LZiY%1N&S{i^be&OQw&r>NLX^ixRBm6S!hFe`tF(tAgi}fBSOW90k zHMIfb6sTlH#~*`uq%rNzvIsfKa-Uz(PYM*snyZ3q`&czWf#KAHXe(f4&4z9lEE##b zb5~QZNxG>{Q?+Yog3Wl=Q*88R=L$ACTCxHJv)bL#XtooW$CP(4Gz;Ji?n%pomVJJx zJ^1;_Y`U@i`_Op%u(Cee%JRx4TR&b+6CC?C}wZ87F+sENHVlgFm!D9>%1JB#E%uXa$t5^e; z_X6j*bBA<;(EGR$%|vc}Ffq-jhDi~?2a1v@nTteUL*KbLLtP;AdSUGYs+E6!o6Q0@hnt;_%xGbf>C*{S+DD3l$yZA=L2=l^bG;$WlCXaP}i z`|*w5>jKkw!7vnCRl@|;NUvReXJ4uRK{V4Eip_9!3g>ibtIRW z7iu<9UA+oOA#&M|#$cD}6JyK*K{n1nQldZ4?cXDKC5-r6qC6n9)fUt_{!Rowm<_ER z1oTr~7b107te@V^V%|wv{#6BRF@2U4*o>E~VXCs=Ww&~r6D1Vg{KiL^B)PF=Pc$L` zCbh{erPg4>ss&jcR=q3Q>NFp4yJ!vTd^LzKVvyVr?YvcIkAKnZqk)jYuJs3{lvhZm z&XaV~dgXSTe;hJCM})kG)y|2jSj~lBbaX&qVA;ZUny*+ctiS3wk{bm$jWc9E^sg6l z2ekI9Z~dC%c;+k^*hkSRd1=h3n27nC$24PJ6qyoyNU*HVq%vC7CiARGj-j%<=}(B! zAx6jZjH+_;GRs?=4U=`%%De)3+bNdWch0=5L;E?-luRGb2wGCJ<7d?WuLUQF^uX;Z z5cozBGJavqmeWLmOw|Y&vI0E=^DU?n)6CsWZr3MMdWYpcBv{{B=AlPWFi{$+<%l3S>A#4u#qDJ{xeFN3;_Ut27$ zm*lk5+~!pS9Dhdg2(q`&CBsMqq-G%vS8zSnMP;JRVAnY2;BpQqd@}9Y>ge1p62A-< zV37lf-^%vMV6@Fi`>jyHVJ_3Mbkhb2S}n7(VAs19P$4WG?>pmbcb^mRmswRq)Dfe` z%{aC7jkZ0xSU~uDQW8mqK4c$v43W|n-4cBhsupz*oL_gkUw-Mv)bK%sZ-cmfE*w=y z6P*ZMl1e2*WXl@ROQ=OI*A3Ae*!pYDKz~d1bm{H4jI6}Y>@?tzR6U`b2kyX6EPTGu z%cR;OHW0XY%s00NSjNzssCOks$j?J;qO0vBK^k60_(aE~`0vW=f>99HAPrloHSV2? z&{iNWFX4&P{F00Qsbbof8l|Qxe8BQkDwh_~)#Zkv4W?4-XFR><%ZfK~>i{ zT=)VAptD(1V!Hk2Qr%G8kl&3**s11mk$iPoxmZvl$@p?M&d3Y?gt8pCHP3cx1WwSw zK}(8d6v8V25{&z6x6%Wn?n$6hJOmph2NgAj`vn$9vyax*Gu>`=cxeZx1RL(Mx;2Zw zk;s`$rpiwbdmGwkrlY@bw#>^Ft5L~4O?;(Ft%eL94oW2zaEsjV7=<4-^I>ECXHlc{ zPgak9F(!y(Xrm#aD!LWNSM7T;e_S&36 zH`;~elgLHs0`1~Ru}}_I_7_z*xTf5o+XI3uDCu3NWqG`bq~@yaS;UCHEmn4gvY$$R z?M&rzyac$08x79tE6OwxUP#P#P~g=K%#MFZS(ypvZO!mIkr&Uq0-AatC~1V*$JrIo z!MZ=uio^?~W$tqvFo;tIb1EED+AhdVAZgl@>QEV%o!CxAqv~lVrb?{ZMQoF~I|fpv zkXqyExpw6_PpBqaYV9ZxUJT0!+T6Z^c^o0{1f-WzO*ijKE?f-T0BYMZdV(9XW)z|m zuKmS4o9D2#`vW!iu)Ci#L;W?)2`2>jGfG|Idd$J2Ha3`#KVfQ*T*cTN%`U?BS!4so z7JjtZkWQ?DAdIW%g8n-7LCn|7KY)xmWQM_d-_g0WX8|x44^n1H?_ses&YtKoor#=us15Xoo z>u+d|Ri(4!6sN;mWJ&P}b3_X(rF+K)!DnTsuk0WtSIdS*Y!0koB>CH@O0OfhC7sD= z<;J4WvUaRnd4?h8-K@!CRql!A=B8=in}hjEk&7-+ycS~9v-Z}I_r?loEuaV5pQAhx zH`>RL3sw$Cl|fO%g&kJwqInV^Fw0j#(SuR>*DF%+Xn^H*9=UuiI~?RBu?|?spTF`q z;l1@hQ=dR|kW*$nPJQ?MufUT#Y6gPi%38Q~>LMGVSxvllTN&g7y>TP3DR?63dYZri zz9x!*yN$hX2_UC)L;}(qVt2-G9bw1H(@=w%YYlIjl!_4ryjjj%erg8*oQbI|>DO&} zHD~_jSAJJdzMu!-`k9~;p4%xa6*oz4{ls(GdIo+Yrya_)-U{|!87cEjF*tr5+IXNM zsVbW|4Mbt(=7wx{2o$BFP_Zx?+rpn+r8{oot~gYJuZ=ISQXx){Mm=t`>TA?SiCd%E zH~7_#%&3}t-F5&(GHC=r^Xv?c&--%dvGDta&oba>cOCkwzIdwX9!pESBD7dC1iM{F zj;w|QA!TyIZ||(`32hlR!M6;T8cKC*74I#AMTxs$*^39zqRO%}7Fs~(Ufsg3GATx$ zhe$(qh%gnj{IG^EpEyehu4dwB0b_AK>Jg4^DO!7P6u7jG&PD|YUb2C;6$cnytu85_;_j)YUT`xROs#M}>BW{h8B1y)NM)k=bc0m=7 zMWRcvZ$;PLy;fk*D&OQ}gh^~U#3qXVK3}arN@->xJb)F`1b8V9`l~Evm=-e&-ev!oeUk$GtZN5F$18na!d;fjU8*S5W=n0HVvbDRXob{KtHQuQ9UjM|O#$kK zj)8u_yzCiC9CK9&LX{h*XARhdH*5wyHD>N;_I=#oJ%ig%?7J!rRmr%#Nnb|5z5xrp zAv*_4wq8Y^OYH~R(oI}mch&CTTC|(1L}PY94^P?QY83!60nMkPAnI7+uKa@oz={8A zc0zB1z+cPx4*PUapFgzK6Ve}FPr;xp7Srla z*_V0t@j0L=;39A@7wEGEYwaE_1t?I7hHE=*&M zvUxTE4|o9DPeXdQEbv@gFONY(f%58EFwyT>pH=&Xk~O;2y*lqDF8G($mjyQWOVedR zSBku40hY^y>m#Qo?jeU~#cN*|T9Fkm5qXfz-@iICSf+x2IXJRBjG%A=E7t6#-v>_= zxT9#))gUI~lqFFkag!U7;;5yP#$v$Lnte;?dn}m|7i(VIq$tjTwt;pM@w?6x7o(a zP3SS{lSQPHYZkyw;~~sWul2GUkyWje8W#X``i+=!!ucK1G-$1@rtXcRNyae~geqYL zToiFWbrMJ}P3YM}((hOhn`Vf^wXC=MNENOjx?0@mo^?#@np7F^ueHN(a5lJy!Su$L zF?o`m5Y-34g%@Cu_oYU_?vAFGMd()USbaQ49GL|xG>~dO2CJDvx#|m5Sg|5|WX*uT zm8DE-?mzrb0AUHH_(73s4%VWw&bnYQSsbx}TcPYi6NouxDFx2$_CCtu-maSURG(Zqdz>D4!e!E|G?DcD=HN~mPYdQqPPX-` zu=2n*eWKPgle|IMq2GB$jP5~-f9(N(8&3nd&Dz06$KT@>qy_IAOx+W3XdztuTj0|` z#3zBV7>&AKnWt#XxY==>U#Cs zF&c7ez_Bpd)EHwt%k8__cI(vK+1yNV@BjuZVlYd}zlwGV z3Qc-oEgF=|HWbe3YlL5Luj*>Ha>K3?d*G zFh^)Ve8xV3nZ{)NX2b%(sEZmXsxd$Tg-!vXo~BGooB-wb*&vk8pxxI06>#1!l9d!@ z)8QeArA)VyBb z$63(s&0l6#>1=dM2s~}U?I2^Bz3l=2KS$x&tuiikw_obUO~c)~Ns$q-66%>48CU(|IA*p0>1heAmm^D9>uw*q+z$&VAHg!~fJDO`jQ z@lrkaPFHElf3Alw!wy&o`g~lycd+5|(8*G#@sIW&HgudGeHS(JABgPhu*3T6T#e23 zni|-k0O8j5(1^BP0-L6fWUa%)!#PCDb>;N%SDu$kMu^9c!x0cNYm$+El4a zir$|w3X=RhTr_IQbS@$$>*6+Z#Tz?XQl5JxWAE68bo9Pd$RI7J=BQPXe5B02xn253 z8k!c*qa(RVTZ4a!oMG+Qjf_eAbgmLyXhbks0rKimEvpWzqK@ zM~259RSFLNIwvf8u24{mb4Y*g%5|(dzpJ-;u;7S{92fgt&&vvc+h5Fd8&6EM)Kc*ovA$2 z0p-UKSG3Nqoq^SNOe;^3Rc_DYp=!TmoP0x5uBJfnp0Si}jiT?7;*{j?3HT+U|^hJL(#j(QKO)vStL-kD{emO z{e@B1&!>GJ1)1R zey!Q_TEls%^73F?Pvu?D{;;=y6mthKe(j|id-M!{?#b;X|9x->A&st~AgOls1-#ss z8DiG)G<9UT#^ZYhe4YI4?>|ykeFdCXZX3z5K>BWCE^|jW(|^{WfHdXkezL;?)HK0D^md^x_&7NtP?wl9&dxyS%Z|F z;AG8D35uZ3@O4+M@vkUZ3x`8h=p#2T(lVAjMcuX?x!ST;7L46)f!uLa)W8c@T^P?m{QDfF3 zGqovGhdY~`_DOItJ&explMzrM>Q&t+ zyH>^3q64`V-VO0v+1+*-W)zE^o}}}S=+FP(FV#~vx=nk@HoQLvQb;A@rvDr$fPxUq zmyM|MsM27g;HqAoD2p!H#RdWjTLu~P!v9*>&^A#i-=BI+vbz8XCY!f3uSd?mIT}p* z!D;?UDExc-U?kU~ocAO>(QEPyEPbq6z_e6z*3pK%v_&zvYsf?;2N_1HJ6K?8txm={RV@_B+9blc6}@ zYHOmR^KGhUKMDND{Hrn|X^YBRMgmG(>e$(E-zTt_mlPup zn$x4|-u;SS)fe4WpdE8efOG-skw~xpM6e9g*I#pLyqa)k?_g<049&7VW8E@vzB#L_ zi*hD~NydTQm*!=d7&O*}bQ_RjQGW!4^Lrka3$v;%eS+Quhkf#NPL zEMJEFI*;7)l2m<3$tsSeBcHgH`7=AeB$g3{A`AiN+Iwg|_j&F3@4HjQ<9Ej~@u$@+ zmusl~*EFU0N{6Ed0QeJr&Bt-)(Bmbhs8^{QHOmJGoB2N-w~c~2Q+>MX&`=x~rR2{u zrFz>T0=l0<#_k2QxPlwW z6-S>U&FoBtceo9G1uxsUZjm^`&RA3W!Zcv^Nk)BdK6wIO$P)HC!x`&icSZKKAWUIv zEtFx2f{z}hPxXovx&vl*9XgH0<>Nur9a#u%lS$$N-+8jwRktfViM4=G1-dT;$|dz* zbCfoxg>o1EfOgg4==n}UlCt}Ua*XVZ0jt#pd~H&JtHf}t6*)+IB~fp~O@dRCn` zJ`c*l8ID)7e8E|+N}5R4*Q(T1G$t+BX}VsU1Zgc7z%1zH_b@r)Zc7e!x=M@Ln=SX^ zZ+Oe4Mr}GY(QwaktFtK$H{zxT5!C@TIS%>NKh=>=PX4yW$Gp;#*^AUC^t->fovPQEVyP7~BL-j}aP9 zZrJWIK;+0qwA@}bSt$sFjAKLx_&?QS9r`Od0-XQh`mPsgqB*`DOJ#UEv%-MNl4!-s z9TYq7Vo7M}x;(J0EyTnFH{Xot{VtBTZQcj+)T%{Ad3xIb-i&mec8i<#3_2SH-exV?jX^3_|YE&qvuaQ8hbw!T8P`P^5%7fS{LWBFN&0`%-iv!`IdLR~&c6-4NB+ zP(@q22WOyngnTgxqUN?@M=-2Oa{3;F9}Zf_qKz{q)*tw~Sfs^W(A*C)=QMWbj$!3n zH!7wNlHgdj)VNcW-3hd2FK_Jb;~Bg>^^Ex32}4c`*em{gR$y-p@32;4RWJWy36N@F zK;Yy9B5((+slU(f6fO&E(;^cgnGlLy2gn48*zT1HsJ2494!iyE-C|?B{T8i+U)CI< zWUMX32%5@Clmx0cM89l8WH_~0`Y*U650K%F7IjoxjH|agyI!p>^9jgpi$oU-rvm4& z?$7m-NZTWg`!#yhWto#n%!Q(f-?|q50?L8Mv5b1}Iwo=INF^m_+DcjuOUlX%T%E*7? zfN{L&`n}oMt7&XMu$hdU#%qciG$fX-!TqgXAUWxmLc3xX+q2~HH|9ih#36jvky4B> z4Q`S6eaD5)#RZOKJQi_SyQn(AS~LeXQQ0pv)XRbwEskU|5JCk^J=bvUW2bPhAYy}X9$16WS@zJS2(Pdj!A&4 zdU>Fx`bhCDkI~As@(I9M0a!BL^9}0NCpaAy_jDxPu6$YJ(NQq8=iMSIw8|6v|kojT{i+f{ewZehRjS0Ei17j#{<5$8Y zc#;YIF?SN#&Hr{jB?;a;WD%!G%C1rS{9nxuX18CrJT|WXY4)LPt zm((tFH>-PqqW?B)54`=c2U383dK$9Q^>I&8wqwzS64jNyk14bTrI=x*Uu{8wGks{Z zUVnYR<;}HzcJoP`WOjqk!WTIj52|R!X-(`7dKrr5!IwPIk(i>E-2+NK{ol3Md0*9EuW-N!9sbZ=)9Y zH8mR`C4m+rkxIfd!j0j|CI2ggq3YjsLZ6M(FBxwMwQiSe{V4QFK=TlzV0w}9>>*R_FW=;yQQEuf`4*ydO)&^ z4&dD;x+!uKa3ohDe;%rSJF7M>27g)fRIpNsVU%ziJVo>vjutxA1)v^Vq(r{#HK4)t zT@fIYX**<@{1d0zsD?CO0(bn-5Y5H#n=fH8oGW^)sDc6QYXGVUi$j&`Bw1j%D$k^- z9x+}VUl?L&Rklr`DxyeG3yB?8?BABS2qli4`eE}dV4Q(+v$tjN>1tlaxWPc8xGEHD z6`vbH%1TqJMj_Z!4*gJUB;+E8u_WqWH8xjynZoh1A@y`9rM}URkfpF)jb&BOS{#+R z3L)1W-!gnuLPdSZkg4We)HJ=^%}z(Lxvh@4GCv}>txKDy-Uj>7s=vI21Q{qX=^vV= zE@yZIfWHkiKVTs&tuKT*CmB1kza*Jd?aDSdfLHMNeWQ_GnZy@LjPHV}UvrnmQdL6| z)QZ_n@rcZS8b_$0QJ)6N2+{px#}@_(P4#o$ftT)$)n)n(W{CyC0~eSpzgQ1FR^zVJ zmd0Yl%0J1Jk{F*ZE*OppVfVA(GeG=w?$_xCxWIInY1U*}astb#Uk2a5Q7|+}O`%e> z+k&XfNdx{gbcRs_HCn`Fflex6XC@OuKS3TQRXfmHYdWNf^O>1vHyVy>_46+|?^VC+ zf9Ki=;%@7ylg?;fq>mk6&?y*OrYp+$*Nbx>_O(-(bWQ5`^G|tK`yk9ML2%e{nEJ>J zKsN_QHJ)xbQs3qe%vS#`AE&~!$%*K0rc|phbXGpQuiC-5DDupm&~y33FzdVX;Nj`C zClc-mE^4y1*+aX$GQfs!JhV_z9A|S3>`AsU{h`>XXT9_p$72Q}CO>Agp?-ZR(=dCl ziJb^+sg0S}4f)f|x8 zl;{qO2Sawd!IiR%AHh&TNx>P&r%MLT(ECm7L(Kna{j0z~EkW39Jt-Y@NJiEd;CJQJ zAW5ETr92`QQ}~|P8_29 z3*{}WVksg-qd9l!_wTut@y74X$3@=iy|0UAsvhL3^BGtaybF zQevf$W;g1f0V@I386NB%VBpdSK!A6ZCkFU|PJlh2&aEH{+Lb)a)s!K5$#9?VOI!3n z) z)-~=9!7X_3;O_43?j9hx9W1yX+?_yzySux)yGzhuA0f}Z@AuUGF*Q}I*WSImdsm$^ zdwNzomr2RAQ*)f)K*`VaJFtL0Fmu6zcPt%J>lLQKMFkM?c{a$olIZB;+z|wldrYc$ zg9P_x4WimT$)B$gy~e!2wcpe0Im@&Kv|so24-$sEZBj^kRAqCkSoi0!Pth?eO5=od z3gNqNo+LlrnIkjInF}6x?lkB9d90l!c>)kx_`C#p-@W`|?-zM}M0~-kd-5FVwC{@@ z4~YekyguFD_3uRB%WflI^Ro(6E8QkoJ<2x=)tm9FLHC^;s`pW4TE z4fXd{iu^8;ve&?upYI%-F~H{skiG)0PSYY43J-Q?NeeP!k0TEGKEHTEV7F)Th3R?(S&Cv{j zM^N$(sd*%pKR=J}P7?3ja*K8Ksk+i$-p@Pg6jc49B<2(Jr~GOu;F{7WbfcL-@T!$G zK1s1V50Po2ckHpAoMch1EZ~84Z8ObSl-%+`ve{!zg@gr#F-j}Ei$GBcN*3@;?{a%& z27D{9W^$A!IR2!<#seq8i#W+GTecst7F8bitmk)d?-$=S@MrzL=bwY7a-bMf?+ix> znRXh6nLYn|qVW)cPc!C(6Q{~~{S2w;^j7q-i_D4fEWadYOzeVaWaBclKRJ(d)KP5`W<#X zyQSL0(+L>M4~^CrgTdL8AgeQbUD!{3CK#t^cT6y*N<=A=&1G8;^c#b|^Z}2{b8>Ax zo6x_1fnHN5M@TA$A>9GN#*TGW-#sn)KXZEqn5{Ev2O} z4xy+5{^&Z22Oc6|TV3rRNO<(b3E@yq*OIU5=>-yGK(yo^ zT#DPdxKh*zGaW61mej%pu~HfVg_dN3E7F_e-#zD>8GBx?x%}Y=6+-%l6t@ukFjU~` zYbv+8!DZM?PqT&rn{iT!K;_C9dyG-d4)CbPmXs*3HtfU1lQt_KNdtiDW3_JLgL6e3evtQWR*DaU)P>xU+8m}{;#Ac+Q9_42N(G8FxxHEaWsQF>mnX_5E zB-Z0U`#{8hG_kk7Y-~1}4mce}(70yBEadYLU&S`t@eInn=Cnnm%QO^j9o(}bA>J>2 z`Pz|OWsA@NSkb+13P>A^4vLa2H5oxn%sN8juop$8+V`Lo} zu3KT6AqIf9zkY7J8ce!2Q;%GxBuQ0ZVo|T$iK{8nGtQT1DY;OJJ|>{kPO>@pI*&51 z?HuUT^Y;2uMYOD>SJsM2nUXBs#oR*=7RUG&s7RJjmFU0Vld?E{ufF3Eb7t+jAYq%B z-K=hlg+O88q4;@#>BlWy-O?#dxGyfsL}mbS@-SexV;>l5x$|QvWBM7jhPy+1%YyJ` zxa!jnG1!EDQ8DB(vJ8n}Cy0i#K_Le(n) zBQ_XiwzjI@d4!x8^wx6Ts-=hd;vZYA@8*zST0zgp!uR|pN}mc99VA>Q$3D%Z*< zRUbM3oszs#D7o2`K2EPw?d{ryl6FJbG~_~`6?*4#bBMD@oZ5;;SZPf@+8A7@e6q?S zeyr$1P+~>H`gYBk$kPV3YLZI?9sZ8k$cb?CZwGsGSDv|{agb)8)Es5XnNx+9!z;`H z%qd979eAMg{A#x@(zIlZn`H*C-tb(<)3v;fL(TKb)zWmjd|xKtEVe#tM!l1 zjur^_2cN4_Rg=&lkyhc0PFnno2k#Ir22D+{fK37&CWkD=Ao-eFvrVD1!g;N6X1f)> zj_OI+o6%K;t7?g>VLw5ocj>MfI;l+o`Uf^;eS#q7y!^><&>|Q`hfp{qn=U&6b@bz6 zPHQ$ebJ;JCmCX7b&*wqaIj~=>KCV#e6kE+2wHxSUSxkjp9TxbS<=dy?tuA~)U+wNv z2Df+GuSCJL4|A|KzR$G>891t}=1l7F>j4#~_B8~VqX1{MSb~jp>B-=Qu%0dl{B}*2 zp8M_Q%=^7y3G>8>!-I0>}%Mw%!ZZh2F+Fjo9;;B)|`Kf z>iR7*$Kc0~M5&VIK*9cX)2J3dGdLj$NIT|!t;Fv{yf_r?l9oodIy~4Swr+lFI58|@ zpKG#9(CE|qb<=s9ZTK--CC5sdlGWwkor7Za#4!g2+=2A5cGvNrZ+pe=LR)o#gw__l18W__r!eN&M(!WS7IER>ZLxX z-Bs$EbM1;|)OVTKoUYO1Nzq$IzIZQ2$sA+elEI3aK!}=pJ91UAuq6?{iPeDW zD)*L@g3jg^GR?xo;&B*;8$itand9?8UQXgC*v^62@nB9(GLAWXO4vT`4|zp_UWkc{ zkl}l(dT^KucWOMv+C~|v&crnCg_pK$%`B>PT03(+XPkk(o-vwFKV`0{vTP6ys(c1< zJHLu<;)HmzxpXr~E-z~)w8Trvy0@aLTDW_A9VXp1tpb|vK>#?jmo0AL zCTGbq#r)dg)n4*t%B3yTpSCpVt&}@Uf0jT>@7tem?tQ{-?bt|wc*ws}jk92!+rOxE zP?ASN1b=(5QN^V*z>T*j@7&Vzmh675ksLuvk`h5nl#WG6PdqcrKx#iIJfDy&p-y{Eu)S93mf)a>a zRXH3Engdd-S}e|hz#PukIM3qLC=eXf5!KE6L@ZL2!Xn3c*hJI8WRvIr_EV2l#yioh z{T@mc{%EXvgpxEC*NyYTfz5Wd+BP5=lzI2L5sxm&zpz-Mv=dOoU7ZR+d@14|t0;*a z?YJ37q4tBsY4R*<-IcG#7PNAo?bo0#bL&_p52yg7+^bo=F!#jGs)*3t&ejC6KA=EngMAKaxk<;A~}BZN}}Ft zCWF)yqyB1Z6FG3UCPY(%0!KYUHnt;TK6c=Xj({=*?CMn$eIm7ESwZ^7lFuvj>pxq1 z0O@O0*b?Mk*a{{CbZ;y6FwlHzv09DKToHkP_^r>XyOsb^p1-Xt!NUYp0l}B@sDBX! zAT|w7YF4z^6ZGey%}%l9?4#b@B3^K2(=3Et>3#=i1&a8^6%p|D<>VtYANcYx={mtG zV9LOw1atFlhx_UQ?{@X^?UgM0^EvzdmxZhI2AV0NF%FdI1`bkj)b&>k-Hu8UqF;s9 zh=$%_hzlF{!Cb`rC?|r*t7X|MyhXNOT*m5;GV_NmB&~MpE1Ms=vVzzL_X3DgO=b<3 ze+hoEx8;dphD`(|>`9;vn0fi+i|z6h2_VB@0U=ww6emJxQ?4XtW?@7pio-ohh?SiT zbYnjfC|^>}Cd~}+#eJ-pol{QXv$>bO8yz5|WGbzv<+hJt8&<`f?R9|~52H|%=t#R) zyqr1OJ|9$&^(Z4lQvQiECVl*oQ^KaU32=JNhkIp|2~B?v-_K|CW4wf*;!_Z9J|Gpc zc%_Oxk3MlEp;#fjC|##HY3sC8(P-7S9P+!*0Uqrj!gmmPG@rb!G|6aPwDo#(P^!%w zC>qqeKJ8Tm3|8qJDJ@0p>zC7MjJ?aTgl0pVgZoEfE9f44rYF0U=}RyKCPXi}RYw#t zUKX&uCbEd8Z==cRi0ZNCZUPVTT!0eI51h$ixx+0T5(rM>qP_%d&Z4$aVu~*0RK`%@ zIq9yPtOqu!BZx_zbV#OO!ipC`c>27P=%F%}T{v+a&Kzqmchk}e8Dpy>Z=wh=@y9&t zPs#D_ovt;IU^O6({7ZhCY=NMO^??dJU?|;FEl<0&^6(7kbQpfUgp3BslLBOpwL3K; zC;>UQrnWV#*Ez;2db-R>`?4aoD7#}fd8n~CnpmxA5E{~B`OE@-Z${{lY`~C`AnY01>(KQjZ<0Y~v`*CZA8ZOLq;XiCfF>JJ6dei|r(ILs0to{~2b{{E z5>^|`*sRu*DJ&6`_O2{qtXX$xmxK=JnmZxzXRzGdSUFlN!U8-wv;evf#8H8{1ruV? zk*9`C5jfcKiLw7X$(h>j|P}Am>r%_d_*WnQYrGgf>)r8H&!1TCUc{x9f=|W zD?jIXWI%%l+H_oWpg7U(=*X(E%r}TVs9K{6oy^eiYDwx|Simt3T!8Xn zp>vUJ=K6xRlNlpC?E*}fww3!DcPSWzke+qNihjkhvEcZjD~eV1>K2uv)o8m$-vOwC zRXi#G+oNA+1@$w(hFi#8b(cim8 z2&00JA@mAJBL50Yz5Sz>1a1>!kxAg7RKw^ZUg^Asa$!cx2cX%gg=)|&D3;R~d;}Xg z@+^2>FWw+R&b>R`#O5rJ(#N95ty%o&p}v=B{Y53y=wNYqsn|I zks8Zlz^Tnf7l))1a;@mCLM>kTDhXCMft7O0p2AY$?1FGnMarwM-X3;!eCGAp2nmzQ z=G0mU5LaR!LauzXH>gMP9YbOLuG5S_YF6>O`SrQ^75P7^T`(Yjl&kplV?MoWSxtqo zgT9MgA%rQv14dz?VDG?L#Jeh2wM672_&XpLtMJZ9i5>r|gJoTW{+H@kEcuTKJ@B#k zuVc!Ra%|W?+E_?*kcRfa^)7C}spED-?Caep6m?x&rQO>8wNVOg_7rZZT-r5>ToR>i zhthf-6j(_fW#2Aj>v)xtE8IJeJF6d%8gm!N=AmdDphfoN>VZ7SOtk*qT=jAccE;>RkFG2STJb`Ku6D$0Tar9e^$%t>rS>dD+Q?fFyyKb5N zmHt1m5jFie)@|0>QrgLZ$&>N1#8Lj@ai!Rr6cG+rwc=R|^Cp?*DH|qZ0@x8YXrL1; zk@s;XLbrP-#$sY5BgQTO!8IMQF=+v#fOpMJ1BQsOd zDHsQkF!h2!HoWY_u{@3;7i7N;!^OO=gSM1DWZ3Nv7KP^+kc{HB&w0|4>(TtD#ZYrZ z)W7I0(yMrvZYa!fJOxhOV1z<#%ON^Mp~d{D)74XTP*j)vSI=OS3^G15y zmBPa_u^CiX(Kek~ydoRaeWEW^2chP+iaLTBxL~O?=1?^;tNDy`_;%ymQxD6$|aH@fA8+NczlM7^zdz;ota;UEYk8NLjoQxdDYJ>v47^WH(`7)nsN?a`$uOweV<8i7qk8@b4_IY+%E#t5a+eqC{qba)rLXg#hLgC(*Jv(WvEWPw&KbaA6qxu?f)gp$&E4 zGJf^D+|FG81u(K`Vpvttwy~l|tD`n7>E%iqgCKy8^w?a zDrz!c6lU!>m5LCM9PPmC6Z{C4RnU}$D{5(hKQU~%0(f+5&h>b;%k+(BswEK!=d-Yh z)TmqPol6H_XQ7{yJZ3g?Co!rFObBgV^#F!y2~as_ce*F2%@ZB8abS|zScra0K<@9^ zJZC#$;mt$u$47`Ruw(K+0K57Lxq$W1yI<*5s7_{ald9ap4-EGJh|S34Yiq6VbBVt& zBHN`PMtLv|q+`8?R)F+4OGJhF`%JL`wV`Y(Lj`dnt740A z)wwm;Z8}1De82ryr|uP7-9gFlEnM{kaqDh6K=I=twO2U7&8ei}WMuuAM#SKTp1hDG zExxav5GaEe%$u_)qN}!cyQgI0c|F~Hx_2Xw1~et%=U`|0hS<0kc#=1I^rreTpkJcH z&tv0F{l5PMe2UIz?4{zCbjUK2P=OT1plM7wbPoD1ahCE#$UoeA>nh%~ zK7zNfa4^l6TAG?^w(2Q}#KXPHWUwrG1N>kPTvDIdpXpm;oIg-lZ&{~zn zIfSPoDDY*aF-O@?@KmXG@dr@90!?!-z5(_Mm}#X~1JYuC!xgg(QZP%6)zfN~Rk``# z-_o8Hss`xf-9Xh;Qk?Tjvlf(>8QAKBgzF%zT$ibZJxVP5R$})M;f|~wXim5uNNGWp zwQh|ZA;C!BRLv8{uE2dBJkiAS$dt$nNboD8nUmO3&1jPo0!PW{OhxL*!)3H6s{#y$ zOV&6402VxWcRw`&7%Lv17L)KNw!ZtEB(+eM|(6O)4)ai~O z5_AxD*fX54m>G!62I8DU2N7;HZ2{`k=4cW`)RM>+KCr1;KSd?ERvMbVh3VCnN0%5l zF&{Pw_ut@;iyZp^7C;+$tLjWS%sQovobR+RM{G5sJqTE*B{Ao$aQL>}26(Q9ZE27o zGzc^#;-yw875Yn@9;#ij^!=~&3%%;LlF5fd3VJKmDK-+Wvfauhg{%W2cmYFYCWlR- zMs<>|8Wiz+I;Ar0yx)duhMLa0ef4Xfn#xO}4l3WId+AU&;|nTSP?-B3JoMnJQ?b*S z3CV1}9aG7c4w@YKSRBsfHP398$hsy$UP9p#dmT%pauRl#A}J4dbkk z0p+q0%_51V#6eEK)w`eY`s9xNb|F(s*c`x;vXr^suni6q zv$)!cvSvOP>1}b|ls9Q};zXx^%;)Isx|9{!T=igf#1+Hy3pR(0N`Tv{wD9p-hH9VuiNib& z;hLww^JeLn$4n^? z)q@~CTOZDq53bg34Q2%#6EHP!EglqD+;35m)0(EcX)I#A#9sMQxDvl)J(e-oJkvKA zC1d9+w{*vqP_E;E0(+~O&o--)0(jP)gEKu+WDUK>n|`!KWuyW8023&9EM{I`^_~vL zdCui{A8($gxrg*^iU&x&m0C zINtIJbf&MFK!alNQ*neYz+S}WJpHogu#H(bnEu|5c`vPa_ApsIaz&HQmg{>^jwiB= z=Rr&LXu5D5V{w5T?l#?0e#F#-v4M6g(%w(A6kl6p{B?GK@E6+tKs1R+3YHo+ylL$D zQ$Ofqf4tks`#$7bacK+xJS?#*cF%Sju$rOk(gc}Wn z0*t-*P>D5wwoEDF4cL)%L}Jopfe?;dZ}b{yYpB>kw#K+Aou~zJx$wmgCTE3{#F>11 z;^I7|KYxUESd-;wqJG%!kRA&n6k`Rl4KglwO_iG31q&=T^eL8U>gy4uG_+>Ie%z6C z=|4>g!C8?d&Y=~mfQ~0oe z@ZEf7_~~S~`1-O95JD4=MxaR&5b(w^F^N=_?TO{DSwLnwsbBfD_QhAQK<1*!^0Q>@wLk`j;k-aID;iu}7(59(L>;P$l*#Y_ zCPR-9pjI^TGa@`bPo9891{Ejwj13PQi3hPKlBr<}v7#VCd`OjRV`j$i+$UpPP_QhD6>Zj#D-~@BB~+oU^F#sgP1tsnm)hi z+t%%Uq7R$Ah<8PEoL4SuDb-R z1%N0!uQeRO?^wCJ6z|W!`UgWfh#=LaRCMEjLtXl!;UoceuWn#r1EdST>*qGBDxd-J*|vO_aHp ztkJ2;&t#xV57Mp@LwnmS7m~ln7O1$e%M1{)WDI~JN>Bzbx0@G-XqeBB@`-Y_mnpEE zLyh+-Tq|4r3a;_}_-l_wzq5SNW;XY@iHMcL1J>`AFbH|mLBw0~RUJb9AIyEc6t*Jj zefls76=>n2+T*ajo}!4 zTZ|9Sgi-MV+xe)G8=7$$obuRz$6SqXZ1G|!+ z8cR3w{k2o}#%fcg>}Vu+G-P3Sl5bE;8MdX>@oX9Qt;kY?DAGdzM&3=n#2OTMNb`Wk zHnox@vKv1-FZ9}T-|84xP?FC>mCL5ItVPpPk*u2uz3^8D5+57TBh8J0v(tWnjKwK@ zQFks5J-_Nrw)1J!)Pj`P$6nyd!=+IlTUMO11-Q>zWRX;Q-~nC_CpII;BZfJ#p$L#5 z$j+FS_BYH5Ix0TcC*x?Wz?EWxm_SqaE@@XSB{?dyx9@XBk3Blfthlb9Es=_8D4KC# z56ePQJHRLX^WwpLDq#b%_s1ImNwfZk!%&5Ap!-*rvaTrJBqN=~@=Lx{;FYl?;x?*H zGiqa5XXEzFl-}O%k_l?@O|E_^8{|Iasd_`P$c{Vg^W|l2uY0q|>pB3>N?5Er^O#g} z=|s@NV0W2^?Pnb7ez2-85?gyV|(y|}j4`(4tKrD39_+c$Bx@3pr8d}|N$kSGAh zw*!q$;j`22;-bR|(c2Di4@4L1RvNiAS?!a#8Nx^7<+H`Y$mj0(pezyv?MucC*WGa1f7b!3~64WpD;1Kfm+$#R52^fSGg022>< zcL+HM(~V=7x}}`Arv2Z)Rk<6yuT`5fb)Itw zR`^^W-`aRR#Hdcgy}i9tE3weBKKP`zcf*hN_FHITcufJm$npeig}*$>eU3%=mQalQ zSe~Vo=nZ$opjkA!?$gP5Jw=p8rO67BNhJ62;smfRI==s-{XwOM^9dFhVfqW)qw&Y= z{UW}Ng_m?r+Zyj=^xD&h_|?OV0l+Uy94GIY@Cdh?w{OxwyLIpD(E@5%YmjU6O@my~ z!#N|}WDB2Z zZh`fPhP8D8alToBYJO>2;*KQww$BtScVS#TMT&nbJ;$i~wke?(XAgi|FZsi=XG=Z{H;IBSX}@4diM3d zTJ|u1PM`rM&$hf*xYXzHLH`K616}6D-|rpsmG6S@P748l8+>4~fb;X1z`#+(x6}%;27@;_-fLv9OT6!Q{$=6!^4R;4Ho)-Z_j7K5 z&C7UT#xTH67z`leDiZMbGQv9n}5W1??Tmeq&+7{$q>* zG=PN%Uab6e@cPzd`=2Jpcedaf9#}stuo8~`O?02=9hz9h1EYp}b3p#4uMY{tTBH0g zGZyZRDG1D3`|Gdl&G`C1%)cz$bv!UN_rzcMY;3g6)aN@81JDk3W2eyjv-%wFD z|4R1%85AetJ39&y0T{XYH{3t$bj1I%_YhHN|8KqC*ZyAt3H&Rd`@jBVkr3aCsQ+2y zzX@Z%g$JgC^k2XATjc+puui16CR52=rIJi8Nv!|{|6d-gIL3Wf=9$af=FZ_ z?jGv$aGZlX_3@h><3vA%>-e2EGZx#-JVaol#SthxU2lgfQtve#% zw|&C*Y-l!2sSE!A0-{#|0`lo!fp`5SZtefgrsp@?_@XykTp-H<-v4CMzbB@o_`Q?z zVt8Q6!QXKHM0xucek{fTKK}zF9O8i~l)MKoc}V#Gm96a$KY)RCzYUlYh};ePKS|?B z8&&J@7H{&~#rUtd+h*T`d_E+5Ul~$aw&=Mx!pPeS()^3)4HP)ydS4muqqiiT2aeAZ z0vnDn-=WDjXzve155zx4c!y|?@xW3S-k=Xa-DCQ9=+B^tm);ErkEx+Nmi~0`{{RCU BblU&` delta 27618 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 q7tw#^abdR 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

    =Xd7#o8m)hC>U?iFl_d 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 diff --git a/rdrf/rdrf/testing/behaviour/features/exported_data/fh.zip b/rdrf/rdrf/testing/behaviour/features/exported_data/fh.zip index 5bc80b19127d8c4a466409343b08384fc2a6eddb..754bc7316f75c3560d1be56a2fb4b1d5e2acab3f 100644 GIT binary patch delta 14943 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 delta 15058 zcmZX*19V+o)HWL1Mq}Hy?KEiY#x_oDpP;dg#%^pjcB3YZZQeBf?sxz9{%4G2?)|K1 zVy(6J9t(4&)PU{PfFUZ&fkR+`{Qc3(P$nP}g8vnaq#r_!;X?$`qrQW>AEf{JhYj4a z#!Fa%1N<#82#A(KgaHBZVFv+$ekYiJWm1q(7nx7jc3vGu9ol%IQTK{T<$&J1)EP~5 zQ+N1!50x z1H7CbKK>Hw_e^+kblnll?3c)-)Z}&4e%658U^tu3qY=`%3{)kOPI zS-tk+(g@qqdNXgq1Ho{XkDJZX*1F|mSMTweor?rV7f|ju128Dk-dfki-em}cc>~=d zLU|J3=PUe`@RgE#0QCu8^bDnZ^&ofPDvVz5yOYDC`wf|EkUO5oSrGS??}~JY4Y- zz(rlrWxH7ryM|<%cJ8erUglfJ|2&kaGAnM+;pb+=R!_(U;8}=5rFl@WaK-`>hz%cc zQ4x?tV64ix=(XJGflk>|e%{gWUH;Wx?$87+FZ%a|sx2biMHYR1w#jbJyEXAl4#}W@ zHnLwvGyHbACSztq92Rio8XdATHp@iW!4wkZ)!@*~z*ayPeIB39p-tr6Ha6Dw){Wua zC(CQllk4!PzRp7DFzkS}yvhNX7G8&(KBqBvhC$fGRlE8%UOayB`W&@-zvLvy-;_ig zR_0PfOKk0fBCCb-3kLdoi-4tSgO`Wm7pWj#;x|4*k`6k}zYw6AY3Vaa5uu!Um(DvwqzIknIqM!6f?2 zJJZF?4wZ{bF|26j&4)TK8Z9xAdg<|NxR#m_I@-mPC#caop^9J>`v)|N&``LKHK@t9 z+oF2ef&)dgQB=&MEp+9?z{I}k^s+QQ(>vXu4%)0d&f?}}iF(>{W^*UtjpHLRi;1&` zsIx2?lX5R6(ZnL^N^TVbMjD&XxFN;d!#Trji`WE%pm<bV_;Z1(Otp?&*p+pp_OVxT|`iUi|$)Srxvb7S(d6K|p zHRJPy^%|wke9yfAth%8|eEirg`C2Ryu7x#FJ^qbf(6__+Yk`{1TVWZ?Xw+`6{5+3z-7pw(-ffIMeCO0O<=SP0nCnqc($^ zkLV8D=XfLMahif9c-V0NlpRuIElIrVZ^H#jL^)HKP}vVQiWvH1WI1eER4xLT)5Sw_6ST|R&+cCsiG@mqjY|fwfIEp&qY@gClM+(z%F7@; zoz-xe0_@`g8hvkX@?IT0jL(EPju3yo%vC-(FiL`=$7DrTivEJt(-@|NAW{MA4GkBB zFUXj~IzV*>5UJz}>SJ*xl@2NX1P^1~u2gG}B%!~`ExcXMTX?xxLW zr*=D89GaiM4RP3rw-TvKd-%U0L6#H1$OI9eMdw4e}m) z8xZDNtb+`}TT5{1VMK0v<_y(-)sW62pHadgdkV7w=Y6Pzh%PwZ|r25BqbCxw@FA06SwG|m ztjdQZfYbPpxyby$^9Xd{036E4{SutX|KNha$w*XS4EzUPp9?Py`cZI%VD=%^5H&w! z6{6mUL`2g6E9>o$nEnxSkqtfuId(Wi8&L0K7>M^jE}#)21&}EU5_l2|4HQAa{ZQ3I zG5nC-C`KPL7g-Ewf%@s=Iuup=!wMv9X2$|32uM2QKP!wtLsaN`3bfr1XZ45}lHh;& z^%~gMU~qqjP+X5Gz8rKwbv#CZxAQ7@-Pzj{O-*$h-=$>AP0c3@f-@S4M6$*E&rONT zbKJXu($dEA3B1H+Iu`EblkP1W=YEN+h@CW@qd*^l;`OztvBscA~GTu?&5Q@uj+49Ha*OBW$kJE zJZEw?aU~VZ?&vxhiipDZ`{^5FNgpS1s&|VirxbI zn08KPg_9J6yBJFl;h1T45u)hRiTyPi@w$MQj=L&vZ-A%k+wSEeV60+;5x$|4h=E~3 zeVk>H3VdC?5T3GR2{%`nTqQ5DHUlC_y0;OGT=zlC!@ux3m+UOQB|VU~Y-Pa_;wSmS zBGqGfpFi`N@Ec`NUr~5Z@Y@|Z^{`+Yg7o=~{GL+7%*fX_p9%$qU!ab~0;=GTRYfrv1nF$qISTtQ-lB?E?wIi;k z`xi6`n;8pO&bD*i1!M1WBGqC+IF4Loj0hi9S3Sx_5D=3=V2KzFzYK8zp#|CCTcP%h z;txD)E2LksRRGJl)@quW?~#?Yo>DA09IAU#TZR?mglXkUX$U59@e+i=%%nOqDUoaD zSWR^|tr{vwESLuYJ|<8qp)3*!EORmCo0((ItcLPIMElaSh^1>7`1w-^u7qaeku@7i zBGrOv<&k`(15+b`E{^pzkmbp!Zk*Sla`p1VbE2Qv{Q-_3Ei#z%C>Z_l%!%-N*=5nk z2}n6H!^_(aN6=d0z)Qr+j)DV(AEw_-j7XlN;0zFai$^xY{Uw20y9E&e8u6sC8vbO; zV-*Pax6Ac1Jt=zxuq8jNX$5>tl1eH`GcC8*2lC)06M0xsO!9@8c|0j|1{*J*k5_;m zqOvPCtN;*aaJ!DeXyJ>WLW(k`k#6CWcSrMjm-76hrH3{YOP9!XI>4Y5or0uVco-Ot z2$E8u1E$P32nvejhwOGH;eY@Iqujnyo=&i{RH~rvTP;LyuWB;rg#B@pdKcUxauE~Q zTP|MCT_Rd81c@RZQbvVJvh5P-PhT-^T&wl>egG=kXS7nOQ>&-}wYo3cNE^kwhp)Cw zt<401-zINgI=qtJwN`F5kkFvtsB#HBk(noMtp{|IjGpc13?7 z>jPk7PF8ZjmrsDg3*IK}eyd!wcPVdSFp~Ek;4*8LiIQUjR|pv_Eypn(#mquiqjKpV z76C%!3nv(rm_c+bRNZt|!K?}i>rIkl@}8t$Y>oSi+EJ7j#VK=QOQtYz8iN?1IVJK$ zvRLU1md@&1_kS^evW_gO-JTT-!KVaeUINJ3MkcgXG2mOE9!_#dGQ&B;gHyRwHt%H- zF86{o2H5=k#0twg*i8Yhg9<&y@nu`-tT0ZDlgWdelkJ`q$sNtA?i|x(rYTy+cGOiZ z;l%e-`g+_lmvemLXsG#iUW{~aa!|Dewl8a%%~Izv`^Mv>l{dT}nHf}7^x*lIL?%G$ zONL#=#!39uA1m5Sa zu5NYtIp6)LmoK}%CaO&IgOqwGS=gAPlDUt2=O3ynD?mQWD9IbtlTnJ;H zrZm=msi#PGhGeYxj)O4B=Y!p3_%m7t`?zNu2fkAsXea|8hbvmN*x zU~$lg;^}>uKqPA?Y<7Z19oEv)X6|*)s)FYb-d8G)3t-W)@IoB-9O3=>=EJ{vFBk8MEG{x!%3mWPYq5 z2b|&?OHh`j`H0!uk5>U{nC}TZv6NLI(vFSH>2-$%4f7SXRHWDbx@IZ>SzKDo8U3Wa z!|8JHi7n@fuyYieg#IXr&#ZF~{pBe(mbVd;T=^Y`lu4R^+DjXli23~#Bj!F~pjP6I zNSg8;AKdjd%}QB;Bv?6e0(3gFu+++o0?7U&v2+-|p<;M^=O5NqjC;Cggtz0qCyfeY zTChv^8SVz5IppKB30YS_>L*|gS`6K1s8@KaSUP6cSx;E;R?HgAeH6-$ifP#jDr?&- zEATB$=718z#B*|U%f*tuO=J;ruS#r~R7k<6vav!08B0;Y#PS;NZY0j{vah#XQjw)Q zj41aZTFCA%P!osKKLj*uesaQs;z`G55yH4g<;vv-Url<#Hkj4{EZD;5)69*7zm25e zCFE|?TYY-kFMT#KhZqqyU)6E`IwJH)4a+w+<#DQkLio++)PAS+YA@TkGWYj_*@fsG?)HcqY*yoyjle=dgEqknF#nt*#74F8p+8_0P?$U) zk}n7@PtkGvuO0PyU-&V8sRU%luS`3(e1Y@enCju$MDsP<7 zOK&mSN{S!_F^pN)EuP!2>lm}lo&7<|df^jxg8?$TDjGUquf7O$&Mpl2o*g#<0KT(7 zTI>NQYdP8L-HVEMR|?JEfLQ_io2gDW>`KX-O>R-?vsKr-;`MgkDcT}bilTKszO$ve z>PcVuk{@c*fY|K$=v%GYFltR`tnWYjpY?k;rcrkr$uubf5+B#cCg;tp%p_X1zUElg zRlmSfYMc0q7LYgDtr+BDX>z5mFFY*Ux=kAk*{m)j;hzdEYSw%Iq{B^ev935d-0NJl zUBAXw@R`v3{O!)W@Gh%<)$XXt+QedXS==j0!q3S=4KT#4obINW;Sc5;;&%e^#d)G7 zV8W7Z5-PLYfN!f>xdDSgX4K7$K$)R@zvpSx&^XfAj5C#2Wsr|%?|fv5Y!N8 zkTe<>{D=H(@vc}m*kSx>EuZJGs~!W%{l*49nlI`M`s#(%&xhJSGq~t#3{I=>?7rvL zgHU4A2Qr_!^Yt&*@y*&U8r4N&*-F;61iAK(eFgx*u5kL)B`@IWvaFPqhAWWUTttS{ zs1Zy!;gQ&18F;7N{GhM1S%^UfmbLyC5>BGW;eGP6aD6xMp&_1JqEGuMq9 zZUguS)fAWLgy+dav8gU(eDUZKp|&01YpGsk&f|X8JDZpks+Q5i<<`mL;jGtvfwHpX zrL8T;E@&|i-bSLEa2eo8`TS|22KW7i+L=42t`22P_#P;gY;N_EK5`RPwyBaE_-B7w z%qaG(Lzyp(xQbPZCOM*1sZt;&Lj+QGa0L*NCT=>>O^?IO^}X~FM*k}nPB~70w$Jg( zp0ac;rBrqv`kMsJDf{AMB;YlbYlg-Pn~S?s4iEB|#7gIm;W9j2z29Ts)4uPQZ!JvW zt*ef{ixSCC>{ht7!q5d~Rvr@2P;4e3iw@D5}0YQVV+x8%P9l=Q@t7tmXm}Q!a zQ1l9+m6_q;e4M4W5kPdTLFvFR11*1>)N50A9iTr;BUQM?>Xjnh+y~;e92W&Y=0MG9 zCQpIQR<3BmxnS@bny;9z+~WgaO)~%k@Q7GTi=H6?WF0LH#2bbknF>~+t)mNehB}Vc z?r0XZjeOs=S~)Ig3C5w@9n`6DSqDNO(jEaite%jnPPaI*bgGejgl$9CHY`D z^dMF<>wgQ(;9os1B)GK+bawJu?tJ4Q#Jjah{?3vzB4?l0`PcfTER5^~D(&!}PvSFJ8^;UkAp=9hy-d#@Xfb z2QkYjPLm?Zb+4qE14%nW%Mj z^s%Sck>mW*pGYv9|FK*Rt_j?+AJzney~t*o)^bpDmyCiO>aRr$?tb z)x~ON7ejGkA+G{@y-%SSca#h~-1XijDVhm6jDpM&S(bb&Jw~bYHl)3-so)&3bB4j9 zyJ=hHo_unf+DE^3=Cr+HcSX8~j1aiZ{JhGK5XWE&NN4ZDYt#7(1l@EBpWp?}#t|lW zu5`6=T-{7*rFdVWbtF9wnOuM2u%%W?QxMOdG3^L;2bIApNmk{6&O$V(YnGyGG?w3#h?=MAz!I1~G-WD2PHv1{bDAH&T z`5mFq0dgI`wB^UFK+M}RunNYDnVhG#lM>P7>85e0t(sQX$cC@@EI|7%_85jNrxatS zUo&}Vpng&s86}iUN7OPn)~qfY4nq6B&``8kO`o&}J1T3Ddl%F%uDN%ld1bDVMfhH@ zQ5I@FW+7wgU0=gDhsxh5jp!j_l(Wv4=yIjy0}_;Eeh^A!?BMpTLV?H=WHIdf9>GEC(*q3h>f-@F_>qsp9#G}7i12|a} z-)AZE$4xk<-5}UzbVDORW9B1S+$hyWEsB{87;DnE`xR1mFq;Wap@F$lbv5=-87vMl zz}hwhfhJf}|AQp&B78A{0UUUPB{=)1Rd>%V-Xra=e40MI=x4%J2tL|e31)_LSjWwi zbuJiUcxr;iG>f#_+SV9->pey#neHtk@ki*j1AT4gjAC$^n8CKD^$8V$3_Y5^M9iS) zg$jce?c1vSn(MvXGKwHD+A*(?@%Sc&0Sw-XX(Fo-EG_3R$JcFJ-q-oC4c~v0j`WSG z;TBc4d#=_dGKgTTkCH)-XYP#?V-zd2Ne*@r7+bVC=eI{Cya*yk&PLd zy)b7jK+HAnM>DusqtS-pe3FHjRZ}Zx$}OrivT3Eyb7qFBS}8YA#p|%2Rgn%o$yq>P zP&(3GJ2ZE*ACUUypQ6)D_mz zf5f*WlX4X+H7wp2(jQYxp=aJ=;8ld_srrHd?zE z!7Rec>T+Q0Un||nib4N^DmxCD=I3G<(POoXkM9ZH&tYM=U4KPm%aoZl>?L*KM3czM zhCP(y43{~pFGny=Ni&N5TLj{%Dygn595fh7;3$g$n$GI za;&LxvdI+J8LJ3TB31({^F=n8nim?}L^m!d0^!%;u302NJ8@F^V z(p5quI%$hEkP`}LI_YQ%3h9ehr4ndFs>rqhvDtY4LYFCjFsw;8iiie%{IShy|6FQk zKA(~f6a2bG|DMf!MZB>Vmpf|WYzy^0#vL4e7a@~+1{w)~;LCFKnvay*#?zy(kfZyO zDi|CU$Df+k;Ph?VDFSm<2?ZXJEvm?@dI;&r*D24pW-FR{pdqbb2ESb-nv|}1wG*7b zTgfUqzJnSi8KJ@&Ik|AH6F|q-3r`M^34tu6heMDx`8qK0%5}eLRp4*+s=zwz)K?B=7!jITFt&S}DO)uY zw#IC{#Jtqzlp$|J8OsoV)O}WYFk)CPn8|$0YIz+O_O~kx49H$m_GXClNxna}Ok@^v zuL&2tMGmw|v~S;fq|y*rO2mXE5yn%1@eq_!QolHA0J2s;tH5Sn1##J2;TT68inSx# zcHGkeSCF$V4wQnwkjqRDJIIfqRw>>jX)#*5Hr!;wzgCcV#j04!S9iVk<#`wW%y7wN zb=qdxILU1KLVTUDeV`{%@%b!QwQKv7w1igjZ_{&8c1B z=Adppn8?GxT}kw*6M5l8BQ3aM!Q<^U7fb4Q>FuW2k7W-csok$wHvk;Eqv2`D>phj4 zFY9jsJa^)_%q6NfgCx|P>E;_+HvKB~+CsdtCGMDd0_B{>hnpqt?E3Z#TY!V>*h6F_ z0RFtW?#lsK{|@;qWD+>z2AAL*9xe`2ikSoLMs(gTe0OLl;XED@>rcMMu(s}s_<){r z-+~zw0BESSV&98_{X%*ew4*vwB>v6glQ~1|sK|xL55IH4Qg9ZU2EfhXCA6PI=lima zPjD9ieR3Rkkskk!4{zjb2rEbdbXLF;plh6Y_DJ~1Q;}Rgwv_^L`yih&Dc|>)_>Bi& z=I3~MomZT=p=C)D{xOD08U-Lp*Bh}5{zU^;k#7(w#cpQSQg!@^Au zdl`c>p#utA&Hz-={TaLR^?vuFzYAOMGo@j^pPb&BU8~C!3x5Qj>ERqcgG4p~BoRs! z*V>%V`V9(K%`fj-Sm?+Xj*u<*zr+KYotvF)UL<>V+2!2%^d=pl(RY{!d-erMJ1^9u zy?=`J|B*>Z*_muPe1aYh85AACRO`Z2dsJ<48jVlF*h$n+2~1v@P}bHQhBBv`>}j~y z+aLL}%1UTMw^z)QNtzkp+dT&Z*v@wUy6mB^d;Kc8X!4`sfQE(nC8Cs9YlNyT-nI`L zjDWc&GeAKgP^6jdnLKQ8L8t%l=TT%gBP6ptl*btsRo7ab6t&!oS%pd(fc;exv(JW( ze>b|5m<;Xb1f>`qjW${h+OVcRcM2sW2B%LBh(~a=y9E1XBpn&Wfao#;!0j3B*OycZ zD69wsYb4jf#$w^ov4j~DZe{6aN{`*Pgp}mPVoFJWemm(%GDh8B49=bx!0A`&g=iJS;C(rrRNu@d^m(*Eu=`SWwlOQT7mNc_}N8cq)ctwBX^a9LPAq>9>kq?u~l+noocnDGaKlxkWB2ZFAVR+uuY?Z zE0VJXXHYIg@X@$c8&Sds&-pq!4{m3pPNLY1ej6^za=6#O5z74*2(Wkxdia%uH#pdQ z&}Cclke+Vh+s`f`J8{z~jc4JI53|Vc8d)vhSz9B)IiPQ=xSG**7&DWGbL9uT*10o1 zt_ayE@#usjU;ew(#=6|*>A#FMgPKuvAD0$ zI&8&m$ZFWlM0bSn3fNVJzw;amBEuz( zTI7kk5j6-7e%~+^bLUdSb&vnu(r-d8*_WYB5s0EhDL?Cjsf6%)Fi1+7+EY!O= zUqQ8gs#MmME%0*VKrqX1rm-OgbxZ9xxG5^rA+p}I zhEPnl#N?i0HozM(PE_6T(x=RX;wQ-0E69Qsr#oEkOjEGR+hmAbk_sYVO;SYdFjT5q zH^f;JO|OkTW4SSvuTo5HtGFY2A#ud)(bkZ}pFd?+O5WJcM>i#hX`F?+vP9JUNatu^ z^en^Drqp|rd^%k2P2W@P3oH__T(7(cv}Wp~Z~A6giHnx4x&lZ6GVkQf{+cYRq)oXZqVlR7$zgrZs|( z20Day05$J~hcvj1nLYjH)Sk8!-GW>tcmQ#eXVCu#qjM4(L>7K=b>P-p;bEJ6^|aG? zV%9iD3OPVIlOo8t&tu6_-DGNyePcXDBdeLa!AL(E(cabOt6FtNf_=KJ4rP#!H!9q? z3k1wF_)ny|8wyP5&Wvb~)r2Scdq&)FA13x4H(mXqt-OzfXfeTJZu zqLF>GaPNaMDS6%N(+s%Vza?RScE7jf@&}lFmO~wC=i%FG`d))}Bpc#seK=d@8)cw6 z_*sD~f_>-H?^5SA!`N03BH5@LKl4qd*VN0)h8 z-H`U5!Y&(eky54l#0Oga+fbf$s61P~q#oc{YjEuHGQy{K1Wki}LU=&!Qg{GG7;7VT zB+0APflHi521}?ICBTfiBgId=wz?j(45Fr~G=WB2FHg9%_9M~_JB--dPedq zl}DYOGRmM5e~v+$B}As}c9#I8}?W{AWnOS;B^Mb?e>!A7P%NHN(xOWU$93h-4W8{^Bnj!_a5h zJc>J&63oW*G%?@tw(HwPOq9gGBA6vfAdV`(A@EiY(P{@TN@yCPMxJ9R!K*wNic`>6i=tkCf*pp#<9(vAyBg&sipcu%wgD?~_vjSkLoKmsbv1pAdo%e|!HBjw57+(Jqb2FPHC3Pisz` z)IMnCNB(?_yF)?s8VPMh>GxW}r}{u=u?RxbaTqecJKDJ6kxM+y0T4LLOa;-R^yU=% zoXJx%LBCHTF(BwW2P3NV%EA`tLfm*V;Q!?^PB2n5I1F(Al;h}(Is3ffIA zyh5HnY32O1;b&l+h;Dk%6!?r|3eInudd$eVx_J5Wg5;$K7rmL=J82fxz+OJ-xDEC8 zw8ta)^h8Q3o{bUoknE@UDifS{r@mX>0gdkCs#x7Bm3G|{@K&;aE&bHBCT6)uyTX~e50h&J{a6EiiR%y zWi4>_)K7d24Gn9+hdhQGHp)xOCr><#b9e~dm=3gUE?FMQWVLyTfTa$(z$_=eU|rgq zAS6X%nz8mu6|mHwkabKxz=(U?8ck-JR_gKPUU2U0>ybQt>+`{}bDD0$Wc%IALdlg~ zTBh3%`=MVTTSGwxzgdeXEJX7BVt4!F&dv*VzlU4gtMH>spyEp|*uT!Kvx=JxM{vRI zh<(N9e?+;jP_H;W(-#Xkc5lW#SBziyQ$0(*?Jwt()D2kAXD%TAgSGjoc;n)2-sxnM zkHqZx_DR2LtyEpe=N`!bAM@F1)5kKU)^20u?rb;L|4Y5DJ9)0Z*KSas+5~y-FM6(L zFudeDq$!n$+?j^XPwGfJ5bWu@LAn0ONJ^Lx9qyf<24K0rreyemLMMmzIV;;~94@4q z7ok$+F4F@{5{P?HmE9rO^C5lQz2`!#Kn9P_^yJtOr5d3{1T2o%LT9n!Aq-+OnTYD# z?Pj-l5Xxzs{}A$m{etGBHTe_z)A6@Ygl*t#>+&?}d~5ZHS_A%CnlYr=Xaj#Zr<7YJ zG?boIn)wmmH}j38kv~!NSP;&=VapAOr}fO`y^l$NkZIWD@RZ~urQUnqid?gMpS-Wz zM31^qd<<5$pO~1pcj|7CS(kGBp<~)%WEs!9kwZaR>`~~WNT#9cZ|0${C+{FZWgnzA zaUa1cb_=~KeJ~I!wMd3dcEvq4;TtvfwE%&aKZJuhs;S$Dj6`!J!4OKTt;l)yiG>dq zEfJsrzOlQd3{IQjdxkK4oIh2zY9}6?pX~E6Q7KyRUO@3)E@~a0cYaG1;$;cFv73w+ zLQCK;?-c4_xOqMd*|`|y%hh-VthBm9b(%KSOftwze&rj+oM|7xEI@u9`}rJE8u7JV zt=_}aPw?^6?}910MY7m6WSlV=`p!zn7RT32fF{qHNQ5uC6Sd1-QI__(m=^c@ksC|sG+Zu@-*N5&*G^Db z4BJh$&A2~-vgGefj){-2ke`Nf5O{-c1AIU(e&|nbqlQXWjzR{7Hl2#@M`8(c9GMq= zTbx29>F*^WEeGnF$%3DE-5w>sm_Z>EP`jNkIDZ)FsQC6B+lnJ zbA{;Ty2FNDbj>e0|KlhkE%X}9k$j&|+xqf5PT64?l)f45E>k=Wyrj6Dk({fc7+|2# zI`iU|FLcjoDUrPnmst7K)~gJ8`NOVDA|mcb1L^`xs2s1%@~a7vy94YFrz?Hpk90l% z?}y)dEs;+wEC#Ed=2?$ldV`N%P13~IkfpB!K-qpE@b$1>es5z!XfC$`5vbLA%RNv^ z|6!4gSJ<-SdFg<$)jkasg^c;-S1`n1chD&gad2H!3sRA zDdwp|GL9M)yFaIymiV&Q?Z+sZ2%JLG#B-{g{CBOas(;XSB0I#*H(aW#6ppdmvzB$< zE?=15i2mOkWthK5qv~BGcs`PR>uZe2{-yCQ7@PjP5HPia`pD<4wj%vN3TCarK7a+= z(0>#I`!LuK>*-#^4YP~+nQI2^?crdKonuT2n;!hp_qp3sL@Why=x8XOQ61sx~^ zNB)1f`RE6rWeh%;H5~8)mEk=VoQU{ur2nT?(f?ST_-lt2s2xf9VfwEw8~nR2(|fx3 zzZg#=@xhYe-&r)koG4VFL=@@=Q#%SDY!l&sV44qT>>ZLu{BRtH2oEHVM)-i4qVd7< z|G}Qo|7@ncLtsenOm?6$5h#w;E|4Wo;iHBDarmI#?|1)l;X6@L|MEWK`A?qve~d1^^ErUr@&8&=KK{Ky zFy7su1Am4?0XZEs{f#oCk%mjR}DVIred;|-s7xU2g z-o4`Q$0GmxoMYL15S4+%A4CEXs(68SBHw!xF#g9PuH6T*8u)P}6F3EYf6VMZplEx9 zzdi7wpM*)6_V}(pO9BEy`5%3H&x9UapiUD0M>BXP;e%Ouf2cPkVShlA?@;4ki0l7) z$5@i_!RmefvJ-8ffzHV|9}2PW=!x%#jgjPkPx`?-bnO4v5m5^HM?hok&=08Z0g1iW zoc2Ef)dha2W(Fbw<5K>0RdxzK7<@30IG6yq^gh}7`ysn{ht&T<3_!lre=OPe4+3<^ dJA?uBPW|^a`}>WE4*gKvOQnU{4gKrs{{b+QoZ|oh From d36768da82fd2affee9085e7719a4e7528ae4fb0 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 10:53:19 +1000 Subject: [PATCH 30/34] Remove version field from docker-compose files --- docker-compose-aloe.yml | 2 -- docker-compose-selenium.yml | 2 -- docker-compose-teststack-base.yml | 4 +--- docker-compose-teststack-dev.yml | 2 -- 4 files changed, 1 insertion(+), 9 deletions(-) diff --git a/docker-compose-aloe.yml b/docker-compose-aloe.yml index 9a57b6ca3..85d6d969c 100644 --- a/docker-compose-aloe.yml +++ b/docker-compose-aloe.yml @@ -1,5 +1,3 @@ -version: '3.7' - x-common-env-variables: &common-env-variables DEBUG: 0 TEST_WAIT: 10 diff --git a/docker-compose-selenium.yml b/docker-compose-selenium.yml index 71c9551c0..76e432b75 100644 --- a/docker-compose-selenium.yml +++ b/docker-compose-selenium.yml @@ -1,5 +1,3 @@ -version: '3.7' - services: hub: image: selenium/hub:3.141 diff --git a/docker-compose-teststack-base.yml b/docker-compose-teststack-base.yml index 4a795ddb1..beaf91607 100644 --- a/docker-compose-teststack-base.yml +++ b/docker-compose-teststack-base.yml @@ -1,5 +1,3 @@ -version: '3.7' - services: dbtest: image: "postgres:${POSTGRES_VERSION}" @@ -26,6 +24,6 @@ services: - "8443:8443" - "8080:8080" expose: - - "8080" + - "8080" volumes: - "./clients/xnat/mock:/home/wiremock" diff --git a/docker-compose-teststack-dev.yml b/docker-compose-teststack-dev.yml index b1678ab68..948759c66 100644 --- a/docker-compose-teststack-dev.yml +++ b/docker-compose-teststack-dev.yml @@ -1,5 +1,3 @@ -version: '3.7' - services: serverundertest: build: From ee9d47ee93d5d52068a3ff177161241662182b2d Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 11:49:20 +1000 Subject: [PATCH 31/34] Update authors --- pyproject.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 23aa2836c..8dd73d6b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,10 @@ build-backend = "hatchling.build" name = "trrf" version = "1.0.0" description = "Trial Ready Registry Framework" -authors = [{ name = "Queensland University of Technology - eResearch" }] +authors = [ + { name = "Queensland University of Technology - eResearch" }, + { name = "Murdoch University - Centre for Comparative Genomics" }, +] requires-python = ">=3.13" dependencies = [ "ccg-django-utils==0.4.2", From 21987da7706d1de7b6d9fd937cf152af6ac0460f Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 14:04:46 +1000 Subject: [PATCH 32/34] Bump werkzeug --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8dd73d6b5..0c801c8a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ dependencies = [ dev = [ "sphinx", "sphinxcontrib-fulltoc", - "Werkzeug==3.1.4", + "Werkzeug==3.1.5", "python-Levenshtein", "ipython", "django-silk==4.4.0", From 69dcafbafb021096682adce029d41f1a150ce1e6 Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Fri, 16 Jan 2026 14:06:28 +1000 Subject: [PATCH 33/34] Bump werkzeug --- uv.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/uv.lock b/uv.lock index ca8a3712d..26b97528e 100644 --- a/uv.lock +++ b/uv.lock @@ -2143,7 +2143,7 @@ requires-dist = [ { name = "unittest-xml-reporting", marker = "extra == 'test'", specifier = "==3.2.0" }, { name = "user-agents", specifier = "==2.2.0" }, { name = "uwsgi", specifier = "==2.0.30" }, - { name = "werkzeug", marker = "extra == 'dev'", specifier = "==3.1.4" }, + { name = "werkzeug", marker = "extra == 'dev'", specifier = "==3.1.5" }, ] provides-extras = ["dev", "test"] @@ -2250,14 +2250,14 @@ wheels = [ [[package]] name = "werkzeug" -version = "3.1.4" +version = "3.1.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/45/ea/b0f8eeb287f8df9066e56e831c7824ac6bab645dd6c7a8f4b2d767944f9b/werkzeug-3.1.4.tar.gz", hash = "sha256:cd3cd98b1b92dc3b7b3995038826c68097dcb16f9baa63abe35f20eafeb9fe5e", size = 864687, upload-time = "2025-11-29T02:15:22.841Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/70/1469ef1d3542ae7c2c7b72bd5e3a4e6ee69d7978fa8a3af05a38eca5becf/werkzeug-3.1.5.tar.gz", hash = "sha256:6a548b0e88955dd07ccb25539d7d0cc97417ee9e179677d22c7041c8f078ce67", size = 864754, upload-time = "2026-01-08T17:49:23.247Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl", hash = "sha256:2ad50fb9ed09cc3af22c54698351027ace879a0b60a3b5edf5730b2f7d876905", size = 224960, upload-time = "2025-11-29T02:15:21.13Z" }, + { url = "https://files.pythonhosted.org/packages/ad/e4/8d97cca767bcc1be76d16fb76951608305561c6e056811587f36cb1316a8/werkzeug-3.1.5-py3-none-any.whl", hash = "sha256:5111e36e91086ece91f93268bb39b4a35c1e6f1feac762c9c822ded0a4e322dc", size = 225025, upload-time = "2026-01-08T17:49:21.859Z" }, ] [[package]] From 3a97ae0e54a2c8caebe421bec7fe7148d8fd55ea Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Mon, 19 Jan 2026 13:57:17 +1000 Subject: [PATCH 34/34] Update test zips --- .../behaviour/features/exported_data/ang.zip | Bin 60127 -> 60310 bytes .../behaviour/features/exported_data/dd.zip | Bin 23030 -> 23043 bytes .../behaviour/features/exported_data/fh.zip | Bin 38495 -> 39114 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/rdrf/rdrf/testing/behaviour/features/exported_data/ang.zip b/rdrf/rdrf/testing/behaviour/features/exported_data/ang.zip index 155c045021cebaa44e1722937a517926dd3ba84e..8385ace0507b4e3b9f0f4a8ef6670b23a1077045 100644 GIT binary patch delta 27462 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 actOMmZ>F#9oSyrSQ_BNJSmyax{{I6HR97+p diff --git a/rdrf/rdrf/testing/behaviour/features/exported_data/dd.zip b/rdrf/rdrf/testing/behaviour/features/exported_data/dd.zip index 71fad2db5ff6b38aecdf280fd3d1d7b4f61d210e..720385d9a693eb31e4a51f8e6c8d581e2b62c043 100644 GIT binary patch delta 6860 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 delta 6753 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 diff --git a/rdrf/rdrf/testing/behaviour/features/exported_data/fh.zip b/rdrf/rdrf/testing/behaviour/features/exported_data/fh.zip index 6b46c47b99c85bc7f345f53c437ac16da1225828..bb9f998c06e9c895604df307d6308cc2fabb2f82 100644 GIT binary patch delta 15120 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 delta 14385 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