├── .editorconfig ├── .github ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature-request.yml │ └── issue.yml ├── SECURITY.md ├── dependabot.yml └── workflows │ └── main.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .typos.toml ├── CHANGELOG.rst ├── HISTORY.rst ├── LICENSE ├── MANIFEST.in ├── README.rst ├── pyproject.toml ├── src └── django_read_only │ ├── __init__.py │ ├── apps.py │ └── py.typed ├── tests ├── __init__.py ├── settings.py └── test_django_read_only.py ├── tox.ini └── uv.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | charset = utf-8 11 | end_of_line = lf 12 | 13 | [*.py] 14 | indent_size = 4 15 | 16 | [Makefile] 17 | indent_style = tab 18 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | This project follows [Django's Code of Conduct](https://www.djangoproject.com/conduct/). 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Request an enhancement or new feature. 3 | body: 4 | - type: textarea 5 | id: description 6 | attributes: 7 | label: Description 8 | description: Please describe your feature request with appropriate detail. 9 | validations: 10 | required: true 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue.yml: -------------------------------------------------------------------------------- 1 | name: Issue 2 | description: File an issue 3 | body: 4 | - type: input 5 | id: python_version 6 | attributes: 7 | label: Python Version 8 | description: Which version of Python were you using? 9 | placeholder: 3.9.0 10 | validations: 11 | required: false 12 | - type: input 13 | id: django_version 14 | attributes: 15 | label: Django Version 16 | description: Which version of Django were you using? 17 | placeholder: 3.2.0 18 | validations: 19 | required: false 20 | - type: input 21 | id: package_version 22 | attributes: 23 | label: Package Version 24 | description: Which version of this package were you using? If not the latest version, please check this issue has not since been resolved. 25 | placeholder: 1.0.0 26 | validations: 27 | required: false 28 | - type: textarea 29 | id: description 30 | attributes: 31 | label: Description 32 | description: Please describe your issue. 33 | validations: 34 | required: true 35 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | Please report security issues directly over email to me@adamj.eu 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: "/" 5 | groups: 6 | "GitHub Actions": 7 | patterns: 8 | - "*" 9 | schedule: 10 | interval: monthly 11 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - '**' 9 | pull_request: 10 | 11 | concurrency: 12 | group: ${{ github.head_ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | tests: 17 | name: Python ${{ matrix.python-version }} 18 | runs-on: ubuntu-24.04 19 | 20 | strategy: 21 | matrix: 22 | python-version: 23 | - '3.9' 24 | - '3.10' 25 | - '3.11' 26 | - '3.12' 27 | - '3.13' 28 | 29 | steps: 30 | - uses: actions/checkout@v4 31 | 32 | - uses: actions/setup-python@v5 33 | with: 34 | python-version: ${{ matrix.python-version }} 35 | allow-prereleases: true 36 | 37 | - name: Install uv 38 | uses: astral-sh/setup-uv@v6 39 | with: 40 | enable-cache: true 41 | 42 | - name: Install dependencies 43 | run: uv pip install --system tox tox-uv 44 | 45 | - name: Run tox targets for ${{ matrix.python-version }} 46 | run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d .) 47 | 48 | - name: Upload coverage data 49 | uses: actions/upload-artifact@v4 50 | with: 51 | name: coverage-data-${{ matrix.python-version }} 52 | path: '${{ github.workspace }}/.coverage.*' 53 | include-hidden-files: true 54 | if-no-files-found: error 55 | 56 | coverage: 57 | name: Coverage 58 | runs-on: ubuntu-24.04 59 | needs: tests 60 | steps: 61 | - uses: actions/checkout@v4 62 | 63 | - uses: actions/setup-python@v5 64 | with: 65 | python-version: '3.13' 66 | 67 | - name: Install uv 68 | uses: astral-sh/setup-uv@v6 69 | 70 | - name: Install dependencies 71 | run: uv pip install --system coverage[toml] 72 | 73 | - name: Download data 74 | uses: actions/download-artifact@v4 75 | with: 76 | path: ${{ github.workspace }} 77 | pattern: coverage-data-* 78 | merge-multiple: true 79 | 80 | - name: Combine coverage and fail if it's <100% 81 | run: | 82 | python -m coverage combine 83 | python -m coverage html --skip-covered --skip-empty 84 | python -m coverage report --fail-under=100 85 | echo "## Coverage summary" >> $GITHUB_STEP_SUMMARY 86 | python -m coverage report --format=markdown >> $GITHUB_STEP_SUMMARY 87 | 88 | - name: Upload HTML report 89 | if: ${{ failure() }} 90 | uses: actions/upload-artifact@v4 91 | with: 92 | name: html-report 93 | path: htmlcov 94 | 95 | release: 96 | needs: [coverage] 97 | if: success() && startsWith(github.ref, 'refs/tags/') 98 | runs-on: ubuntu-24.04 99 | environment: release 100 | 101 | permissions: 102 | contents: read 103 | id-token: write 104 | 105 | steps: 106 | - uses: actions/checkout@v4 107 | 108 | - uses: astral-sh/setup-uv@v6 109 | 110 | - name: Build 111 | run: uv build 112 | 113 | - uses: pypa/gh-action-pypi-publish@release/v1 114 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info/ 2 | *.pyc 3 | /.coverage 4 | /.coverage.* 5 | /.tox 6 | /build/ 7 | /dist/ 8 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | ci: 2 | autoupdate_schedule: monthly 3 | 4 | default_language_version: 5 | python: python3.13 6 | 7 | repos: 8 | - repo: https://github.com/pre-commit/pre-commit-hooks 9 | rev: cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b # frozen: v5.0.0 10 | hooks: 11 | - id: check-added-large-files 12 | - id: check-case-conflict 13 | - id: check-json 14 | - id: check-merge-conflict 15 | - id: check-symlinks 16 | - id: check-toml 17 | - id: end-of-file-fixer 18 | - id: trailing-whitespace 19 | - repo: https://github.com/crate-ci/typos 20 | rev: 0b8af0682a6ecfd3fc5cce8240de1415d67d0d82 # frozen: v1 21 | hooks: 22 | - id: typos 23 | - repo: https://github.com/tox-dev/pyproject-fmt 24 | rev: 8184a5b72f4a8fcd003b041ecb04c41a9f34fd2b # frozen: v2.6.0 25 | hooks: 26 | - id: pyproject-fmt 27 | - repo: https://github.com/tox-dev/tox-ini-fmt 28 | rev: e732f664aa3fd7b32cce3de8abbac43f4c3c375d # frozen: 1.5.0 29 | hooks: 30 | - id: tox-ini-fmt 31 | - repo: https://github.com/rstcheck/rstcheck 32 | rev: 27258fde1ee7d3b1e6a7bbc58f4c7b1dd0e719e5 # frozen: v6.2.5 33 | hooks: 34 | - id: rstcheck 35 | additional_dependencies: 36 | - tomli==2.0.1 37 | - repo: https://github.com/adamchainz/django-upgrade 38 | rev: 700530171ecf380bc829a64388f49d14ecd61c53 # frozen: 1.25.0 39 | hooks: 40 | - id: django-upgrade 41 | args: [--target-version, '4.2'] 42 | - repo: https://github.com/adamchainz/blacken-docs 43 | rev: 78a9dcbecf4f755f65d1f3dec556bc249d723600 # frozen: 1.19.1 44 | hooks: 45 | - id: blacken-docs 46 | additional_dependencies: 47 | - black==25.1.0 48 | - repo: https://github.com/astral-sh/ruff-pre-commit 49 | rev: d19233b89771be2d89273f163f5edc5a39bbc34a # frozen: v0.11.12 50 | hooks: 51 | - id: ruff-check 52 | args: [ --fix ] 53 | - id: ruff-format 54 | - repo: https://github.com/pre-commit/mirrors-mypy 55 | rev: 7010b10a09f65cd60a23c207349b539aa36dbec1 # frozen: v1.16.0 56 | hooks: 57 | - id: mypy 58 | additional_dependencies: 59 | - django-stubs==5.1.2 60 | -------------------------------------------------------------------------------- /.typos.toml: -------------------------------------------------------------------------------- 1 | # Configuration file for 'typos' tool 2 | # https://github.com/crate-ci/typos 3 | 4 | [default] 5 | extend-ignore-re = [ 6 | # Single line ignore comments 7 | "(?Rm)^.*(#|//)\\s*typos: ignore$", 8 | # Multi-line ignore comments 9 | "(?s)(#|//)\\s*typos: off.*?\\n\\s*(#|//)\\s*typos: on" 10 | ] 11 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | Changelog 3 | ========= 4 | 5 | 1.19.0 (2025-02-06) 6 | ------------------- 7 | 8 | * Support Django 5.2. 9 | 10 | 1.18.0 (2024-10-29) 11 | ------------------- 12 | 13 | * Drop Django 3.2 to 4.1 support. 14 | 15 | 1.17.0 (2024-10-20) 16 | ------------------- 17 | 18 | * Add support for inspecting SQL using `psycopg 3’s SQL API `__. 19 | 20 | * Drop Python 3.8 support. 21 | 22 | * Support Python 3.13. 23 | 24 | 1.16.0 (2024-06-19) 25 | ------------------- 26 | 27 | * Support Django 5.1. 28 | 29 | 1.15.0 (2023-10-11) 30 | ------------------- 31 | 32 | * Support Django 5.0. 33 | 34 | 1.14.0 (2023-07-10) 35 | ------------------- 36 | 37 | * Drop Python 3.7 support. 38 | 39 | 1.13.0 (2023-06-14) 40 | ------------------- 41 | 42 | * Support Python 3.12. 43 | 44 | 1.12.0 (2023-02-25) 45 | ------------------- 46 | 47 | * Support Django 4.2. 48 | 49 | 1.11.0 (2022-10-05) 50 | ------------------- 51 | 52 | * Add IPython extension, allowing you to use line magic to change read-only mode with less typing: 53 | 54 | .. code-block:: ipython 55 | 56 | In [1]: %read_only off 57 | Write queries enabled. 58 | 59 | 1.10.1 (2022-10-03) 60 | ------------------- 61 | 62 | * Fix a bug where threads creating connections with ``execute_wrapper()`` would incorrectly have django-read-only’s instrumentation removed on exit of ``execute_wrapper()``, instead of their own. 63 | 64 | Thanks to Christian Bundy for the report in `Issue #180 `__. 65 | 66 | 1.10.0 (2022-07-20) 67 | ------------------- 68 | 69 | * Allow read-only-looking queries that start with space, newline, or “(”. 70 | The later allows ``QuerySet.union()`` and related methods to work. 71 | 72 | Thanks to Kevin Marsh for the report in `Issue #166 `__. 73 | 74 | 1.9.0 (2022-06-05) 75 | ------------------ 76 | 77 | * Support Python 3.11. 78 | 79 | * Support Django 4.1. 80 | 81 | 1.8.0 (2022-05-10) 82 | ------------------ 83 | 84 | * Drop support for Django 2.2, 3.0, and 3.1. 85 | 86 | 1.7.0 (2022-01-10) 87 | ------------------ 88 | 89 | * Drop Python 3.6 support. 90 | 91 | 1.6.0 (2021-10-05) 92 | ------------------ 93 | 94 | * Support Python 3.10. 95 | 96 | 1.5.0 (2021-09-28) 97 | ------------------ 98 | 99 | * Support Django 4.0. 100 | 101 | 1.4.0 (2021-08-14) 102 | ------------------ 103 | 104 | * Add type hints. 105 | 106 | * Stop distributing tests to reduce package size. Tests are not intended to be 107 | run outside of the tox setup in the repository. Repackagers can use GitHub's 108 | tarballs per tag. 109 | 110 | 1.3.0 (2021-01-25) 111 | ------------------ 112 | 113 | * Support Django 3.2. 114 | 115 | 1.2.0 (2020-12-16) 116 | ------------------ 117 | 118 | * Drop Python 3.5 support. 119 | 120 | 1.1.2 (2020-11-25) 121 | ------------------ 122 | 123 | * Allow ``EXPLAIN`` queries. 124 | 125 | 1.1.1 (2020-11-18) 126 | ------------------ 127 | 128 | * Support Python 3.9. 129 | * Add a hint on how to enable writes in the ``DjangoReadOnlyError`` message. 130 | 131 | 1.1.0 (2020-10-08) 132 | ------------------ 133 | 134 | * Add support for a ``DJANGO_READ_ONLY`` setting, to allow finer grained 135 | customization of when read-only mode is enabled. 136 | 137 | 1.0.0 (2020-10-01) 138 | ------------------ 139 | 140 | * Initial release. 141 | -------------------------------------------------------------------------------- /HISTORY.rst: -------------------------------------------------------------------------------- 1 | See https://github.com/adamchainz/django-read-only/blob/main/CHANGELOG.rst 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Adam Johnson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | prune tests 2 | include CHANGELOG.rst 3 | include LICENSE 4 | include pyproject.toml 5 | include README.rst 6 | include src/*/py.typed 7 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | django-read-only 3 | ================ 4 | 5 | .. image:: https://img.shields.io/github/actions/workflow/status/adamchainz/django-read-only/main.yml.svg?branch=main&style=for-the-badge 6 | :target: https://github.com/adamchainz/django-read-only/actions?workflow=CI 7 | 8 | .. image:: https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge 9 | :target: https://github.com/adamchainz/django-read-only/actions?workflow=CI 10 | 11 | .. image:: https://img.shields.io/pypi/v/django-read-only.svg?style=for-the-badge 12 | :target: https://pypi.org/project/django-read-only/ 13 | 14 | .. image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge 15 | :target: https://github.com/psf/black 16 | 17 | .. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge 18 | :target: https://github.com/pre-commit/pre-commit 19 | :alt: pre-commit 20 | 21 | Disable Django database writes. 22 | 23 | ---- 24 | 25 | **Work smarter and faster** with my book `Boost Your Django DX `__ which covers django-read-only, IPython, and many other tools. 26 | 27 | ---- 28 | 29 | Requirements 30 | ------------ 31 | 32 | Python 3.9 to 3.13 supported. 33 | 34 | Django 4.2 to 5.2 supported. 35 | 36 | Installation 37 | ------------ 38 | 39 | Install with **pip**: 40 | 41 | .. code-block:: sh 42 | 43 | python -m pip install django-read-only 44 | 45 | Then add to your installed apps: 46 | 47 | .. code-block:: python 48 | 49 | INSTALLED_APPS = [ 50 | ..., 51 | "django_read_only", 52 | ..., 53 | ] 54 | 55 | Usage 56 | ----- 57 | 58 | In your settings file, set ``DJANGO_READ_ONLY`` to ``True`` and all data modification queries will cause an exception: 59 | 60 | .. code-block:: console 61 | 62 | $ DJANGO_READ_ONLY=1 python manage.py shell 63 | ... 64 | >>> User.objects.create_user(username="hacker", password="hunter2") 65 | ... 66 | DjangoReadOnlyError(...) 67 | 68 | For convenience, you can also control this with the ``DJANGO_READ_ONLY`` environment variable, which will count as ``True`` if set to anything but the empty string. 69 | The setting takes precedence over the environment variable. 70 | 71 | During a session with ``DJANGO_READ_ONLY`` set on, you can re-enable writes by calling ``enable_writes()``: 72 | 73 | .. code-block:: pycon 74 | 75 | >>> import django_read_only 76 | >>> django_read_only.enable_writes() 77 | 78 | Writes can be disabled with ``disable_writes()``: 79 | 80 | .. code-block:: pycon 81 | 82 | >>> django_read_only.disable_writes() 83 | 84 | To temporarily allow writes, use the ``temp_writes()`` context manager / decorator: 85 | 86 | .. code-block:: pycon 87 | 88 | >>> with django_read_only.temp_writes(): 89 | ... User.objects.create_user(...) 90 | ... 91 | 92 | Note that writes being enabled/disabled is global state, affecting all threads and asynchronous coroutines. 93 | 94 | Recommended Setup 95 | ----------------- 96 | 97 | Set read-only mode on in your production environment, and maybe staging, during interactive sessions. 98 | This can be done by setting the ``DJANGO_READ_ONLY`` environment variable in the shell profile file (``bashrc``, ``zshrc``, etc.) of the system’s user account. 99 | This way developers performing exploratory queries can’t accidentally make changes, but writes will remain enabled for non-shell processes like your WSGI server. 100 | 101 | With this setup, developers can also run management commands with writes enabled by setting the environment variable before the command: 102 | 103 | .. code-block:: console 104 | 105 | $ DJANGO_READ_ONLY= python manage.py clearsessions 106 | 107 | Some deployment platforms don’t allow you to customize your shell profile files. 108 | In this case, you will need to find a way to detect shell mode from within your settings file. 109 | 110 | For example, on Heroku there’s the ``DYNO`` environment variable (`docs `__) to identify the current virtual machine. 111 | It starts with “run.” for interactive sessions. 112 | You can use this to enable read-only mode in your settings file like so: 113 | 114 | .. code-block:: python 115 | 116 | if os.environ.get("DYNO", "").startswith("run."): 117 | DJANGO_READ_ONLY = bool(os.environ.get("DJANGO_READ_ONLY", "1")) 118 | else: 119 | DJANGO_READ_ONLY = False 120 | 121 | IPython Extension 122 | ----------------- 123 | 124 | django-read-only also works as an IPython extension for quick access to enable/disable read-only mode. 125 | Load it with: 126 | 127 | .. code-block:: ipython 128 | 129 | In [1]: %load_ext django_read_only 130 | 131 | You can have the extension always load by setting it up to your `IPython configuration file `__: 132 | 133 | .. code-block:: python 134 | 135 | c.InteractiveShellApp.extensions.append("django_read_only") 136 | 137 | When loaded, use the ``%read_only`` line magic to disable or enable read-only mode: 138 | 139 | .. code-block:: ipython 140 | 141 | In [2]: %read_only off 142 | Write queries enabled. 143 | 144 | In [3]: %read_only on 145 | Write queries disabled. 146 | 147 | This reduces the amount of typing needed to disable read-only mode. 148 | 149 | How it Works 150 | ------------ 151 | 152 | The most accurate way to prevent writes is to connect as a separate database user with only read permission. 153 | However, this has limitations - Django doesn’t support modifying the ``DATABASES`` setting live, so sessions would not be able to temporarily allow writes. 154 | 155 | Instead, django-read-only uses `always installed database instrumentation `__ to inspect executed queries and only allow those which look like reads. 156 | It uses a “fail closed” philosophy, so anything unknown will fail, which should be fairly reasonable. 157 | 158 | Because django-read-only uses Django database instrumentation, it cannot block queries running through the underlying database connection (accesses through ``django.db.connection.connection``), and it cannot filter operations within stored procedures (which use ``connection.callproc()``). 159 | These are very rare in practice though, so django-read-only’s method works well for most projects. 160 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | build-backend = "setuptools.build_meta" 3 | requires = [ 4 | "setuptools>=77", 5 | ] 6 | 7 | [project] 8 | name = "django-read-only" 9 | version = "1.19.0" 10 | description = "Disable Django database writes." 11 | readme = "README.rst" 12 | keywords = [ 13 | "Django", 14 | ] 15 | license = "MIT" 16 | license-files = [ "LICENSE" ] 17 | authors = [ 18 | { name = "Adam Johnson", email = "me@adamj.eu" }, 19 | ] 20 | requires-python = ">=3.9" 21 | classifiers = [ 22 | "Development Status :: 5 - Production/Stable", 23 | "Framework :: Django :: 4.2", 24 | "Framework :: Django :: 5.0", 25 | "Framework :: Django :: 5.1", 26 | "Framework :: Django :: 5.2", 27 | "Framework :: IPython", 28 | "Intended Audience :: Developers", 29 | "Natural Language :: English", 30 | "Operating System :: OS Independent", 31 | "Programming Language :: Python :: 3 :: Only", 32 | "Programming Language :: Python :: 3.9", 33 | "Programming Language :: Python :: 3.10", 34 | "Programming Language :: Python :: 3.11", 35 | "Programming Language :: Python :: 3.12", 36 | "Programming Language :: Python :: 3.13", 37 | "Programming Language :: Python :: Implementation :: CPython", 38 | "Typing :: Typed", 39 | ] 40 | dependencies = [ 41 | "django>=4.2", 42 | ] 43 | urls = { Changelog = "https://github.com/adamchainz/django-read-only/blob/main/CHANGELOG.rst", Funding = "https://adamj.eu/books/", Repository = "https://github.com/adamchainz/django-read-only" } 44 | 45 | [dependency-groups] 46 | test = [ 47 | "coverage[toml]", 48 | "ipython", 49 | "psycopg[binary]", 50 | "pytest", 51 | "pytest-django", 52 | "pytest-randomly", 53 | ] 54 | django42 = [ "django>=4.2a1,<5; python_version>='3.8'" ] 55 | django50 = [ "django>=5.0a1,<5.1; python_version>='3.10'" ] 56 | django51 = [ "django>=5.1a1,<5.2; python_version>='3.10'" ] 57 | django52 = [ "django>=5.2a1,<6; python_version>='3.10'" ] 58 | 59 | [tool.ruff] 60 | lint.select = [ 61 | # flake8-bugbear 62 | "B", 63 | # flake8-comprehensions 64 | "C4", 65 | # pycodestyle 66 | "E", 67 | # Pyflakes errors 68 | "F", 69 | # isort 70 | "I", 71 | # flake8-simplify 72 | "SIM", 73 | # flake8-tidy-imports 74 | "TID", 75 | # pyupgrade 76 | "UP", 77 | # Pyflakes warnings 78 | "W", 79 | ] 80 | lint.ignore = [ 81 | # flake8-bugbear opinionated rules 82 | "B9", 83 | # line-too-long 84 | "E501", 85 | # suppressible-exception 86 | "SIM105", 87 | # if-else-block-instead-of-if-exp 88 | "SIM108", 89 | ] 90 | lint.extend-safe-fixes = [ 91 | # non-pep585-annotation 92 | "UP006", 93 | ] 94 | lint.isort.required-imports = [ "from __future__ import annotations" ] 95 | 96 | [tool.pyproject-fmt] 97 | max_supported_python = "3.13" 98 | 99 | [tool.pytest.ini_options] 100 | addopts = """\ 101 | --strict-config 102 | --strict-markers 103 | --ds=tests.settings 104 | """ 105 | django_find_project = false 106 | xfail_strict = true 107 | 108 | [tool.coverage.run] 109 | branch = true 110 | parallel = true 111 | source = [ 112 | "django_read_only", 113 | "tests", 114 | ] 115 | 116 | [tool.coverage.paths] 117 | source = [ 118 | "src", 119 | ".tox/**/site-packages", 120 | ] 121 | 122 | [tool.coverage.report] 123 | show_missing = true 124 | 125 | [tool.mypy] 126 | enable_error_code = [ 127 | "ignore-without-code", 128 | "redundant-expr", 129 | "truthy-bool", 130 | ] 131 | mypy_path = "src/" 132 | namespace_packages = false 133 | strict = true 134 | warn_unreachable = true 135 | 136 | [[tool.mypy.overrides]] 137 | module = "tests.*" 138 | allow_untyped_defs = true 139 | 140 | [tool.rstcheck] 141 | report_level = "ERROR" 142 | 143 | [tool.uv] 144 | conflicts = [ 145 | [ 146 | { group = "django42" }, 147 | { group = "django50" }, 148 | { group = "django51" }, 149 | { group = "django52" }, 150 | ], 151 | ] 152 | -------------------------------------------------------------------------------- /src/django_read_only/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import os 4 | from collections.abc import Generator 5 | from contextlib import contextmanager 6 | from typing import Any, Callable 7 | 8 | from django.apps import AppConfig 9 | from django.conf import settings 10 | from django.core.signals import setting_changed 11 | from django.db import connections 12 | from django.db.backends.base.base import BaseDatabaseWrapper 13 | from django.db.backends.signals import connection_created 14 | 15 | try: 16 | from psycopg.sql import Composable 17 | 18 | HAVE_PSYCOPG = True 19 | except ImportError: # pragma: no cover 20 | HAVE_PSYCOPG = False 21 | 22 | read_only = False 23 | ipython_extension_loaded = False 24 | 25 | 26 | class DjangoReadOnlyAppConfig(AppConfig): 27 | name = "django_read_only" 28 | verbose_name = "django-read-only" 29 | 30 | def ready(self) -> None: 31 | set_read_only() 32 | 33 | for alias in connections: 34 | connection = connections[alias] 35 | install_hook(connection) 36 | connection_created.connect(install_hook) 37 | 38 | setting_changed.connect(reset_read_only) 39 | 40 | 41 | def set_read_only() -> None: 42 | global read_only 43 | if settings.is_overridden("DJANGO_READ_ONLY"): 44 | read_only = settings.DJANGO_READ_ONLY 45 | else: 46 | read_only = bool(os.environ.get("DJANGO_READ_ONLY", "")) 47 | 48 | 49 | def reset_read_only(setting: str, **kwargs: object) -> None: 50 | if setting == "DJANGO_READ_ONLY": 51 | set_read_only() 52 | 53 | 54 | def install_hook(connection: BaseDatabaseWrapper, **kwargs: object) -> None: 55 | """ 56 | Rather than use the documented API of the `execute_wrapper()` context 57 | manager, directly insert the hook. This is done because: 58 | 1. Deleting the context manager closes it, so it's not possible to enter it 59 | here and not exit it, unless we store it forever in some variable. 60 | 2. We want to be idempotent and only install the hook once. 61 | """ 62 | if blocker not in connection.execute_wrappers: # pragma: no branch 63 | connection.execute_wrappers.insert(0, blocker) 64 | 65 | 66 | class DjangoReadOnlyError(Exception): 67 | pass 68 | 69 | 70 | def blocker( 71 | execute: Callable[[str, str, bool, dict[str, Any]], Any], 72 | sql: Any, 73 | params: str, 74 | many: bool, 75 | context: dict[str, Any], 76 | ) -> Any: 77 | if read_only and should_block(sql): 78 | msg = "Write queries are currently disabled. " 79 | if ipython_extension_loaded: 80 | msg += "Enable with '%read_only off' or django_read_only.enable_writes()." 81 | else: 82 | msg += "Enable with django_read_only.enable_writes()." 83 | raise DjangoReadOnlyError(msg) 84 | return execute(sql, params, many, context) 85 | 86 | 87 | def should_block(sql: Any) -> bool: 88 | if isinstance(sql, str): 89 | pass 90 | elif HAVE_PSYCOPG and isinstance(sql, Composable): 91 | sql = sql.as_string(None) 92 | else: 93 | return True 94 | return not sql.lstrip(" \n(").startswith( 95 | ( 96 | "EXPLAIN ", 97 | "PRAGMA ", 98 | "ROLLBACK TO SAVEPOINT ", 99 | "RELEASE SAVEPOINT ", 100 | "SAVEPOINT ", 101 | "SELECT ", 102 | "SET ", 103 | ) 104 | ) and sql not in ("BEGIN", "COMMIT", "ROLLBACK") 105 | 106 | 107 | def enable_writes() -> None: 108 | global read_only 109 | read_only = False 110 | 111 | 112 | def disable_writes() -> None: 113 | global read_only 114 | read_only = True 115 | 116 | 117 | @contextmanager 118 | def temp_writes() -> Generator[None]: 119 | enable_writes() 120 | try: 121 | yield 122 | finally: 123 | disable_writes() 124 | 125 | 126 | def load_ipython_extension(ipython: Any) -> None: 127 | global ipython_extension_loaded 128 | 129 | from IPython.core.magic import Magics, line_magic, magics_class 130 | 131 | ipython_extension_loaded = True 132 | 133 | @magics_class 134 | class DjangoReadOnlyMagics(Magics): # type: ignore [misc] 135 | @line_magic # type: ignore [misc] 136 | def read_only(self, line: str) -> None: 137 | if line == "on": 138 | disable_writes() 139 | print("Write queries disabled.") 140 | elif line == "off": 141 | enable_writes() 142 | print("Write queries enabled.") 143 | else: 144 | print(f"Unknown value {line!r}, pass 'on' or 'off'.") 145 | 146 | ipython.register_magics(DjangoReadOnlyMagics) 147 | 148 | 149 | def unload_ipython_extension(ipython: Any) -> None: 150 | global ipython_extension_loaded 151 | 152 | ipython_extension_loaded = False 153 | -------------------------------------------------------------------------------- /src/django_read_only/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from django_read_only import DjangoReadOnlyAppConfig # noqa: F401 4 | -------------------------------------------------------------------------------- /src/django_read_only/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamchainz/django-read-only/055161c12420ea4e90392ac162ac334441673200/src/django_read_only/py.typed -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import sys 4 | 5 | import coverage 6 | 7 | coverage.process_startup() 8 | 9 | 10 | # Patch for IPythonTests 11 | # Fool Django’s shell command into thinking we’re a TTY, so that it continues 12 | # to open IPython 13 | if not sys.stdin.isatty(): # pragma: no cover 14 | 15 | def fake_isatty(*args, **kwargs): 16 | return True 17 | 18 | sys.stdin.isatty = fake_isatty # type: ignore [method-assign] 19 | -------------------------------------------------------------------------------- /tests/settings.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import os 4 | 5 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 6 | 7 | SECRET_KEY = "NOTASECRET" 8 | 9 | DATABASES = { 10 | "default": { 11 | "ENGINE": "django.db.backends.sqlite3", 12 | "NAME": ":memory:", 13 | "ATOMIC_REQUESTS": True, 14 | }, 15 | "other": { 16 | "ENGINE": "django.db.backends.sqlite3", 17 | "NAME": ":memory:", 18 | "ATOMIC_REQUESTS": True, 19 | }, 20 | } 21 | 22 | ALLOWED_HOSTS: list[str] = [] 23 | 24 | INSTALLED_APPS = [ 25 | "django_read_only", 26 | "django.contrib.sites", 27 | ] 28 | 29 | MIDDLEWARE: list[str] = [] 30 | 31 | ROOT_URLCONF = "tests.urls" 32 | LANGUAGE_CODE = "en-us" 33 | TIME_ZONE = "UTC" 34 | USE_I18N = True 35 | 36 | SITE_ID = 1 37 | 38 | USE_TZ = True 39 | -------------------------------------------------------------------------------- /tests/test_django_read_only.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import os 4 | import re 5 | import subprocess 6 | import sys 7 | from concurrent.futures import ThreadPoolExecutor 8 | from contextlib import contextmanager 9 | from functools import partial 10 | from pathlib import Path 11 | from typing import Any, Callable 12 | from unittest import mock 13 | 14 | import pytest 15 | from django.contrib.sites.models import Site 16 | from django.db import connection, transaction 17 | from django.db.backends.utils import CursorWrapper 18 | from django.test import SimpleTestCase, TestCase, override_settings 19 | from psycopg.sql import SQL, Composable 20 | 21 | import django_read_only 22 | 23 | set_env_vars = partial(mock.patch.dict, os.environ) 24 | 25 | 26 | @contextmanager 27 | def patch_psycopg_composable_support_onto_cursor(): 28 | """ 29 | Make Django's default CursorWrapper convert psycopg's Composable objects to 30 | strings, to allow the test suite using SQLite to check the support for 31 | these objects. 32 | """ 33 | orig_execute = CursorWrapper._execute # type: ignore [attr-defined] 34 | 35 | def execute_wrapper(self, sql, *args, **kwargs): # pragma: no cover 36 | if isinstance(sql, Composable): 37 | sql = sql.as_string(None) 38 | return orig_execute(self, sql, *args, **kwargs) 39 | 40 | CursorWrapper._execute = execute_wrapper # type: ignore [attr-defined] 41 | 42 | try: 43 | yield 44 | finally: 45 | CursorWrapper._execute = orig_execute # type: ignore [attr-defined] 46 | 47 | 48 | class DjangoReadOnlyTests(TestCase): 49 | def tearDown(self): 50 | # reset after every test 51 | django_read_only.read_only = False 52 | super().tearDown() 53 | 54 | def test_set_read_only_default_false(self): 55 | """ 56 | Check that, in the absence of a value for the setting and environment 57 | variable, AppConfig.ready() defaults read only mode to OFF. 58 | """ 59 | with set_env_vars(DJANGO_READ_ONLY=""): 60 | django_read_only.set_read_only() 61 | 62 | assert not django_read_only.read_only 63 | 64 | def test_set_read_only_setting_on(self): 65 | """ 66 | Check that if the setting is True, AppConfig.ready() defaults read only 67 | mode to ON. 68 | """ 69 | with ( 70 | set_env_vars(DJANGO_READ_ONLY=""), 71 | override_settings(DJANGO_READ_ONLY=True), 72 | ): 73 | django_read_only.set_read_only() 74 | 75 | assert django_read_only.read_only 76 | 77 | def test_set_read_only_env_var_on(self): 78 | """ 79 | Check that if the environment variable is set to anything whilst the 80 | setting is undefined, AppConfig.ready() sets read only mode ON. 81 | """ 82 | with set_env_vars(DJANGO_READ_ONLY="something"): 83 | django_read_only.set_read_only() 84 | 85 | assert django_read_only.read_only 86 | 87 | def test_set_read_only_setting_precedence_to_env_var(self): 88 | """ 89 | Check that if both the setting and environment variable are set, 90 | the setting takes precedence. 91 | """ 92 | with ( 93 | set_env_vars(DJANGO_READ_ONLY="=something"), 94 | override_settings(DJANGO_READ_ONLY=False), 95 | ): 96 | django_read_only.set_read_only() 97 | 98 | assert not django_read_only.read_only 99 | 100 | def test_setting_changed(self): 101 | """ 102 | Check that if the setting changes, read_only mode updates 103 | appropriately. 104 | """ 105 | with override_settings(DJANGO_READ_ONLY=False): 106 | assert not django_read_only.read_only 107 | 108 | with override_settings(DJANGO_READ_ONLY=True): 109 | assert django_read_only.read_only 110 | 111 | def test_setting_changed_different_setting(self): 112 | """ 113 | Check that if a different setting changes, read_only doesn't change. 114 | """ 115 | with override_settings(SITE_ID=2): 116 | assert not django_read_only.read_only 117 | 118 | def test_disable_writes(self): 119 | django_read_only.disable_writes() 120 | 121 | with pytest.raises(django_read_only.DjangoReadOnlyError): 122 | Site.objects.create(domain="example.org", name="Example org") 123 | 124 | def test_disable_writes_allows_selects(self): 125 | django_read_only.disable_writes() 126 | 127 | Site.objects.count() 128 | 129 | def test_disable_writes_allows_space_prefix(self): 130 | django_read_only.disable_writes() 131 | 132 | with connection.cursor() as cursor: 133 | cursor.execute(" SELECT 1") 134 | row = cursor.fetchone() 135 | assert row == (1,) 136 | 137 | def test_disable_writes_allows_newline_prefix(self): 138 | django_read_only.disable_writes() 139 | 140 | with connection.cursor() as cursor: 141 | cursor.execute("\nSELECT 1") 142 | row = cursor.fetchone() 143 | assert row == (1,) 144 | 145 | def test_disable_writes_allows_union(self): 146 | django_read_only.disable_writes() 147 | 148 | Site.objects.order_by().union(Site.objects.order_by()).count() 149 | 150 | def test_disable_writes_allows_psycopg_sql_select(self): 151 | django_read_only.disable_writes() 152 | 153 | with ( 154 | patch_psycopg_composable_support_onto_cursor(), 155 | connection.cursor() as cursor, 156 | ): 157 | cursor.execute(SQL("SELECT 1")) 158 | row = cursor.fetchone() 159 | assert row == (1,) 160 | 161 | def test_disable_writes_disallows_psycopg_sql_update(self): 162 | django_read_only.disable_writes() 163 | 164 | with ( 165 | patch_psycopg_composable_support_onto_cursor(), 166 | pytest.raises(django_read_only.DjangoReadOnlyError), 167 | connection.cursor() as cursor, 168 | ): 169 | cursor.execute(SQL("UPDATE something")) 170 | 171 | def test_disable_writes_disallows_unsupported_types(self): 172 | django_read_only.disable_writes() 173 | 174 | with ( 175 | pytest.raises(django_read_only.DjangoReadOnlyError), 176 | connection.cursor() as cursor, 177 | ): 178 | cursor.execute(123) # type: ignore [arg-type] 179 | 180 | def test_disable_writes_allows_atomics_around_reads(self): 181 | django_read_only.disable_writes() 182 | 183 | with transaction.atomic(): 184 | Site.objects.count() 185 | 186 | def test_enable_writes(self): 187 | django_read_only.enable_writes() 188 | 189 | Site.objects.create(domain="example.org", name="Example org") 190 | 191 | def test_temp_writes(self): 192 | django_read_only.disable_writes() 193 | 194 | with django_read_only.temp_writes(): 195 | Site.objects.create(domain="example.org", name="Example org") 196 | 197 | with pytest.raises(django_read_only.DjangoReadOnlyError): 198 | Site.objects.create(domain="example.co", name="Example co") 199 | 200 | def test_alongside_other_instrumentation(self): 201 | def noop( 202 | execute: Callable[[str, str, bool, dict[str, Any]], Any], 203 | sql: Any, 204 | params: str, 205 | many: bool, 206 | context: dict[str, Any], 207 | ) -> Any: 208 | return execute(sql, params, many, context) 209 | 210 | def threadable() -> list[Any]: 211 | with connection.execute_wrapper(noop), connection.cursor() as cursor: 212 | cursor.execute("SELECT 1234") 213 | 214 | return connection.execute_wrappers 215 | 216 | with ThreadPoolExecutor(max_workers=1) as executor: 217 | result = executor.submit(threadable).result() 218 | 219 | assert result == [django_read_only.blocker] 220 | 221 | 222 | REPO_PATH = Path(__file__).resolve().parent.parent 223 | PYPROJECT_PATH = str(REPO_PATH / "pyproject.toml") 224 | 225 | 226 | class IPythonTests(SimpleTestCase): 227 | # Depends on monkeypatching sys.stdin.isatty() in tests/__init__.py 228 | 229 | def run_ipython_shell( 230 | self, input_lines: list[str] 231 | ) -> subprocess.CompletedProcess[str]: 232 | proc = subprocess.run( 233 | [sys.executable, "-m", "django", "shell", "-i", "ipython"], 234 | input="\n".join(input_lines), 235 | capture_output=True, 236 | cwd=REPO_PATH, 237 | env={ 238 | "DJANGO_SETTINGS_MODULE": "tests.settings", 239 | "DJANGO_READ_ONLY": "1", 240 | "COVERAGE_PROCESS_START": PYPROJECT_PATH, 241 | }, 242 | text=True, 243 | ) 244 | assert proc.returncode == 0 245 | return proc 246 | 247 | def test_load_unload(self): 248 | proc = self.run_ipython_shell( 249 | [ 250 | r"%load_ext django_read_only", 251 | r"%unload_ext django_read_only", 252 | ] 253 | ) 254 | 255 | lines = proc.stdout.splitlines() 256 | assert lines[-3:] == [ 257 | "In [1]: ", 258 | "In [2]: ", 259 | "In [3]: Do you really want to exit ([y]/n)? ", 260 | ] 261 | assert proc.stderr == "" 262 | 263 | def test_error_message(self): 264 | proc = self.run_ipython_shell( 265 | [ 266 | r"%load_ext django_read_only", 267 | "from django.db import connection", 268 | "connection.cursor().execute('INSERT INTO DUAL')", 269 | ] 270 | ) 271 | 272 | lines = proc.stdout.splitlines() 273 | assert re.sub(r"\x1b.*?m", "", lines[-3]) == ( 274 | "DjangoReadOnlyError: Write queries are currently disabled. " 275 | + "Enable with '%read_only off' or django_read_only.enable_writes()." 276 | ) 277 | assert proc.stderr == "" 278 | 279 | def test_read_only_on(self): 280 | proc = self.run_ipython_shell( 281 | [ 282 | r"%load_ext django_read_only", 283 | r"%read_only on", 284 | ] 285 | ) 286 | 287 | lines = proc.stdout.splitlines() 288 | assert lines[-4:] == [ 289 | "In [1]: ", 290 | "In [2]: Write queries disabled.", 291 | "", 292 | "In [3]: Do you really want to exit ([y]/n)? ", 293 | ] 294 | assert proc.stderr == "" 295 | 296 | def test_read_only_off(self): 297 | proc = self.run_ipython_shell( 298 | [ 299 | r"%load_ext django_read_only", 300 | r"%read_only off", 301 | ] 302 | ) 303 | 304 | lines = proc.stdout.splitlines() 305 | assert lines[-4:] == [ 306 | "In [1]: ", 307 | "In [2]: Write queries enabled.", 308 | "", 309 | "In [3]: Do you really want to exit ([y]/n)? ", 310 | ] 311 | assert proc.stderr == "" 312 | 313 | def test_read_only_unknown(self): 314 | proc = self.run_ipython_shell( 315 | [ 316 | r"%load_ext django_read_only", 317 | r"%read_only whatever", 318 | ] 319 | ) 320 | 321 | lines = proc.stdout.splitlines() 322 | assert lines[-4:] == [ 323 | "In [1]: ", 324 | "In [2]: Unknown value 'whatever', pass 'on' or 'off'.", 325 | "", 326 | "In [3]: Do you really want to exit ([y]/n)? ", 327 | ] 328 | assert proc.stderr == "" 329 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | requires = 3 | tox>=4.2 4 | env_list = 5 | py313-django{52, 51} 6 | py312-django{52, 51, 50, 42} 7 | py311-django{52, 51, 50, 42} 8 | py310-django{52, 51, 50, 42} 9 | py39-django{42} 10 | 11 | [testenv] 12 | runner = uv-venv-lock-runner 13 | package = wheel 14 | wheel_build_env = .pkg 15 | set_env = 16 | PYTHONDEVMODE = 1 17 | commands = 18 | python \ 19 | -W error::ResourceWarning \ 20 | -W error::DeprecationWarning \ 21 | -W error::PendingDeprecationWarning \ 22 | -m coverage run \ 23 | -m pytest {posargs:tests} 24 | dependency_groups = 25 | test 26 | django42: django42 27 | django50: django50 28 | django51: django51 29 | django52: django52 30 | -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 2 3 | requires-python = ">=3.9" 4 | resolution-markers = [ 5 | "python_full_version >= '3.11'", 6 | "python_full_version == '3.10.*'", 7 | "python_full_version < '3.10'", 8 | ] 9 | conflicts = [[ 10 | { package = "django-read-only", group = "django42" }, 11 | { package = "django-read-only", group = "django50" }, 12 | { package = "django-read-only", group = "django51" }, 13 | { package = "django-read-only", group = "django52" }, 14 | ]] 15 | 16 | [[package]] 17 | name = "asgiref" 18 | version = "3.8.1" 19 | source = { registry = "https://pypi.org/simple" } 20 | dependencies = [ 21 | { name = "typing-extensions", marker = "python_full_version < '3.11'" }, 22 | ] 23 | sdist = { url = "https://files.pythonhosted.org/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186, upload-time = "2024-03-22T14:39:36.863Z" } 24 | wheels = [ 25 | { url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828, upload-time = "2024-03-22T14:39:34.521Z" }, 26 | ] 27 | 28 | [[package]] 29 | name = "asttokens" 30 | version = "3.0.0" 31 | source = { registry = "https://pypi.org/simple" } 32 | sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978, upload-time = "2024-11-30T04:30:14.439Z" } 33 | wheels = [ 34 | { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918, upload-time = "2024-11-30T04:30:10.946Z" }, 35 | ] 36 | 37 | [[package]] 38 | name = "colorama" 39 | version = "0.4.6" 40 | source = { registry = "https://pypi.org/simple" } 41 | 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" } 42 | wheels = [ 43 | { 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" }, 44 | ] 45 | 46 | [[package]] 47 | name = "coverage" 48 | version = "7.8.2" 49 | source = { registry = "https://pypi.org/simple" } 50 | sdist = { url = "https://files.pythonhosted.org/packages/ba/07/998afa4a0ecdf9b1981ae05415dad2d4e7716e1b1f00abbd91691ac09ac9/coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27", size = 812759, upload-time = "2025-05-23T11:39:57.856Z" } 51 | wheels = [ 52 | { url = "https://files.pythonhosted.org/packages/26/6b/7dd06399a5c0b81007e3a6af0395cd60e6a30f959f8d407d3ee04642e896/coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a", size = 211573, upload-time = "2025-05-23T11:37:47.207Z" }, 53 | { url = "https://files.pythonhosted.org/packages/f0/df/2b24090820a0bac1412955fb1a4dade6bc3b8dcef7b899c277ffaf16916d/coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be", size = 212006, upload-time = "2025-05-23T11:37:50.289Z" }, 54 | { url = "https://files.pythonhosted.org/packages/c5/c4/e4e3b998e116625562a872a342419652fa6ca73f464d9faf9f52f1aff427/coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3", size = 241128, upload-time = "2025-05-23T11:37:52.229Z" }, 55 | { url = "https://files.pythonhosted.org/packages/b1/67/b28904afea3e87a895da850ba587439a61699bf4b73d04d0dfd99bbd33b4/coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6", size = 239026, upload-time = "2025-05-23T11:37:53.846Z" }, 56 | { url = "https://files.pythonhosted.org/packages/8c/0f/47bf7c5630d81bc2cd52b9e13043685dbb7c79372a7f5857279cc442b37c/coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622", size = 240172, upload-time = "2025-05-23T11:37:55.711Z" }, 57 | { url = "https://files.pythonhosted.org/packages/ba/38/af3eb9d36d85abc881f5aaecf8209383dbe0fa4cac2d804c55d05c51cb04/coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c", size = 240086, upload-time = "2025-05-23T11:37:57.724Z" }, 58 | { url = "https://files.pythonhosted.org/packages/9e/64/c40c27c2573adeba0fe16faf39a8aa57368a1f2148865d6bb24c67eadb41/coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3", size = 238792, upload-time = "2025-05-23T11:37:59.737Z" }, 59 | { url = "https://files.pythonhosted.org/packages/8e/ab/b7c85146f15457671c1412afca7c25a5696d7625e7158002aa017e2d7e3c/coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404", size = 239096, upload-time = "2025-05-23T11:38:01.693Z" }, 60 | { url = "https://files.pythonhosted.org/packages/d3/50/9446dad1310905fb1dc284d60d4320a5b25d4e3e33f9ea08b8d36e244e23/coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7", size = 214144, upload-time = "2025-05-23T11:38:03.68Z" }, 61 | { url = "https://files.pythonhosted.org/packages/23/ed/792e66ad7b8b0df757db8d47af0c23659cdb5a65ef7ace8b111cacdbee89/coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347", size = 215043, upload-time = "2025-05-23T11:38:05.217Z" }, 62 | { url = "https://files.pythonhosted.org/packages/6a/4d/1ff618ee9f134d0de5cc1661582c21a65e06823f41caf801aadf18811a8e/coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9", size = 211692, upload-time = "2025-05-23T11:38:08.485Z" }, 63 | { url = "https://files.pythonhosted.org/packages/96/fa/c3c1b476de96f2bc7a8ca01a9f1fcb51c01c6b60a9d2c3e66194b2bdb4af/coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879", size = 212115, upload-time = "2025-05-23T11:38:09.989Z" }, 64 | { url = "https://files.pythonhosted.org/packages/f7/c2/5414c5a1b286c0f3881ae5adb49be1854ac5b7e99011501f81c8c1453065/coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a", size = 244740, upload-time = "2025-05-23T11:38:11.947Z" }, 65 | { url = "https://files.pythonhosted.org/packages/cd/46/1ae01912dfb06a642ef3dd9cf38ed4996fda8fe884dab8952da616f81a2b/coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5", size = 242429, upload-time = "2025-05-23T11:38:13.955Z" }, 66 | { url = "https://files.pythonhosted.org/packages/06/58/38c676aec594bfe2a87c7683942e5a30224791d8df99bcc8439fde140377/coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11", size = 244218, upload-time = "2025-05-23T11:38:15.631Z" }, 67 | { url = "https://files.pythonhosted.org/packages/80/0c/95b1023e881ce45006d9abc250f76c6cdab7134a1c182d9713878dfefcb2/coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a", size = 243865, upload-time = "2025-05-23T11:38:17.622Z" }, 68 | { url = "https://files.pythonhosted.org/packages/57/37/0ae95989285a39e0839c959fe854a3ae46c06610439350d1ab860bf020ac/coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb", size = 242038, upload-time = "2025-05-23T11:38:19.966Z" }, 69 | { url = "https://files.pythonhosted.org/packages/4d/82/40e55f7c0eb5e97cc62cbd9d0746fd24e8caf57be5a408b87529416e0c70/coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54", size = 242567, upload-time = "2025-05-23T11:38:21.912Z" }, 70 | { url = "https://files.pythonhosted.org/packages/f9/35/66a51adc273433a253989f0d9cc7aa6bcdb4855382cf0858200afe578861/coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a", size = 214194, upload-time = "2025-05-23T11:38:23.571Z" }, 71 | { url = "https://files.pythonhosted.org/packages/f6/8f/a543121f9f5f150eae092b08428cb4e6b6d2d134152c3357b77659d2a605/coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975", size = 215109, upload-time = "2025-05-23T11:38:25.137Z" }, 72 | { url = "https://files.pythonhosted.org/packages/77/65/6cc84b68d4f35186463cd7ab1da1169e9abb59870c0f6a57ea6aba95f861/coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53", size = 213521, upload-time = "2025-05-23T11:38:27.123Z" }, 73 | { url = "https://files.pythonhosted.org/packages/8d/2a/1da1ada2e3044fcd4a3254fb3576e160b8fe5b36d705c8a31f793423f763/coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c", size = 211876, upload-time = "2025-05-23T11:38:29.01Z" }, 74 | { url = "https://files.pythonhosted.org/packages/70/e9/3d715ffd5b6b17a8be80cd14a8917a002530a99943cc1939ad5bb2aa74b9/coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1", size = 212130, upload-time = "2025-05-23T11:38:30.675Z" }, 75 | { url = "https://files.pythonhosted.org/packages/a0/02/fdce62bb3c21649abfd91fbdcf041fb99be0d728ff00f3f9d54d97ed683e/coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279", size = 246176, upload-time = "2025-05-23T11:38:32.395Z" }, 76 | { url = "https://files.pythonhosted.org/packages/a7/52/decbbed61e03b6ffe85cd0fea360a5e04a5a98a7423f292aae62423b8557/coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99", size = 243068, upload-time = "2025-05-23T11:38:33.989Z" }, 77 | { url = "https://files.pythonhosted.org/packages/38/6c/d0e9c0cce18faef79a52778219a3c6ee8e336437da8eddd4ab3dbd8fadff/coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20", size = 245328, upload-time = "2025-05-23T11:38:35.568Z" }, 78 | { url = "https://files.pythonhosted.org/packages/f0/70/f703b553a2f6b6c70568c7e398ed0789d47f953d67fbba36a327714a7bca/coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2", size = 245099, upload-time = "2025-05-23T11:38:37.627Z" }, 79 | { url = "https://files.pythonhosted.org/packages/ec/fb/4cbb370dedae78460c3aacbdad9d249e853f3bc4ce5ff0e02b1983d03044/coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57", size = 243314, upload-time = "2025-05-23T11:38:39.238Z" }, 80 | { url = "https://files.pythonhosted.org/packages/39/9f/1afbb2cb9c8699b8bc38afdce00a3b4644904e6a38c7bf9005386c9305ec/coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f", size = 244489, upload-time = "2025-05-23T11:38:40.845Z" }, 81 | { url = "https://files.pythonhosted.org/packages/79/fa/f3e7ec7d220bff14aba7a4786ae47043770cbdceeea1803083059c878837/coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8", size = 214366, upload-time = "2025-05-23T11:38:43.551Z" }, 82 | { url = "https://files.pythonhosted.org/packages/54/aa/9cbeade19b7e8e853e7ffc261df885d66bf3a782c71cba06c17df271f9e6/coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223", size = 215165, upload-time = "2025-05-23T11:38:45.148Z" }, 83 | { url = "https://files.pythonhosted.org/packages/c4/73/e2528bf1237d2448f882bbebaec5c3500ef07301816c5c63464b9da4d88a/coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f", size = 213548, upload-time = "2025-05-23T11:38:46.74Z" }, 84 | { url = "https://files.pythonhosted.org/packages/1a/93/eb6400a745ad3b265bac36e8077fdffcf0268bdbbb6c02b7220b624c9b31/coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca", size = 211898, upload-time = "2025-05-23T11:38:49.066Z" }, 85 | { url = "https://files.pythonhosted.org/packages/1b/7c/bdbf113f92683024406a1cd226a199e4200a2001fc85d6a6e7e299e60253/coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d", size = 212171, upload-time = "2025-05-23T11:38:51.207Z" }, 86 | { url = "https://files.pythonhosted.org/packages/91/22/594513f9541a6b88eb0dba4d5da7d71596dadef6b17a12dc2c0e859818a9/coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85", size = 245564, upload-time = "2025-05-23T11:38:52.857Z" }, 87 | { url = "https://files.pythonhosted.org/packages/1f/f4/2860fd6abeebd9f2efcfe0fd376226938f22afc80c1943f363cd3c28421f/coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257", size = 242719, upload-time = "2025-05-23T11:38:54.529Z" }, 88 | { url = "https://files.pythonhosted.org/packages/89/60/f5f50f61b6332451520e6cdc2401700c48310c64bc2dd34027a47d6ab4ca/coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108", size = 244634, upload-time = "2025-05-23T11:38:57.326Z" }, 89 | { url = "https://files.pythonhosted.org/packages/3b/70/7f4e919039ab7d944276c446b603eea84da29ebcf20984fb1fdf6e602028/coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0", size = 244824, upload-time = "2025-05-23T11:38:59.421Z" }, 90 | { url = "https://files.pythonhosted.org/packages/26/45/36297a4c0cea4de2b2c442fe32f60c3991056c59cdc3cdd5346fbb995c97/coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050", size = 242872, upload-time = "2025-05-23T11:39:01.049Z" }, 91 | { url = "https://files.pythonhosted.org/packages/a4/71/e041f1b9420f7b786b1367fa2a375703889ef376e0d48de9f5723fb35f11/coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48", size = 244179, upload-time = "2025-05-23T11:39:02.709Z" }, 92 | { url = "https://files.pythonhosted.org/packages/bd/db/3c2bf49bdc9de76acf2491fc03130c4ffc51469ce2f6889d2640eb563d77/coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7", size = 214393, upload-time = "2025-05-23T11:39:05.457Z" }, 93 | { url = "https://files.pythonhosted.org/packages/c6/dc/947e75d47ebbb4b02d8babb1fad4ad381410d5bc9da7cfca80b7565ef401/coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3", size = 215194, upload-time = "2025-05-23T11:39:07.171Z" }, 94 | { url = "https://files.pythonhosted.org/packages/90/31/a980f7df8a37eaf0dc60f932507fda9656b3a03f0abf188474a0ea188d6d/coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7", size = 213580, upload-time = "2025-05-23T11:39:08.862Z" }, 95 | { url = "https://files.pythonhosted.org/packages/8a/6a/25a37dd90f6c95f59355629417ebcb74e1c34e38bb1eddf6ca9b38b0fc53/coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008", size = 212734, upload-time = "2025-05-23T11:39:11.109Z" }, 96 | { url = "https://files.pythonhosted.org/packages/36/8b/3a728b3118988725f40950931abb09cd7f43b3c740f4640a59f1db60e372/coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36", size = 212959, upload-time = "2025-05-23T11:39:12.751Z" }, 97 | { url = "https://files.pythonhosted.org/packages/53/3c/212d94e6add3a3c3f412d664aee452045ca17a066def8b9421673e9482c4/coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46", size = 257024, upload-time = "2025-05-23T11:39:15.569Z" }, 98 | { url = "https://files.pythonhosted.org/packages/a4/40/afc03f0883b1e51bbe804707aae62e29c4e8c8bbc365c75e3e4ddeee9ead/coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be", size = 252867, upload-time = "2025-05-23T11:39:17.64Z" }, 99 | { url = "https://files.pythonhosted.org/packages/18/a2/3699190e927b9439c6ded4998941a3c1d6fa99e14cb28d8536729537e307/coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740", size = 255096, upload-time = "2025-05-23T11:39:19.328Z" }, 100 | { url = "https://files.pythonhosted.org/packages/b4/06/16e3598b9466456b718eb3e789457d1a5b8bfb22e23b6e8bbc307df5daf0/coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625", size = 256276, upload-time = "2025-05-23T11:39:21.077Z" }, 101 | { url = "https://files.pythonhosted.org/packages/a7/d5/4b5a120d5d0223050a53d2783c049c311eea1709fa9de12d1c358e18b707/coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b", size = 254478, upload-time = "2025-05-23T11:39:22.838Z" }, 102 | { url = "https://files.pythonhosted.org/packages/ba/85/f9ecdb910ecdb282b121bfcaa32fa8ee8cbd7699f83330ee13ff9bbf1a85/coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199", size = 255255, upload-time = "2025-05-23T11:39:24.644Z" }, 103 | { url = "https://files.pythonhosted.org/packages/50/63/2d624ac7d7ccd4ebbd3c6a9eba9d7fc4491a1226071360d59dd84928ccb2/coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8", size = 215109, upload-time = "2025-05-23T11:39:26.722Z" }, 104 | { url = "https://files.pythonhosted.org/packages/22/5e/7053b71462e970e869111c1853afd642212568a350eba796deefdfbd0770/coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d", size = 216268, upload-time = "2025-05-23T11:39:28.429Z" }, 105 | { url = "https://files.pythonhosted.org/packages/07/69/afa41aa34147655543dbe96994f8a246daf94b361ccf5edfd5df62ce066a/coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b", size = 214071, upload-time = "2025-05-23T11:39:30.55Z" }, 106 | { url = "https://files.pythonhosted.org/packages/71/1e/388267ad9c6aa126438acc1ceafede3bb746afa9872e3ec5f0691b7d5efa/coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a", size = 211566, upload-time = "2025-05-23T11:39:32.333Z" }, 107 | { url = "https://files.pythonhosted.org/packages/8f/a5/acc03e5cf0bba6357f5e7c676343de40fbf431bb1e115fbebf24b2f7f65e/coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d", size = 211996, upload-time = "2025-05-23T11:39:34.512Z" }, 108 | { url = "https://files.pythonhosted.org/packages/5b/a2/0fc0a9f6b7c24fa4f1d7210d782c38cb0d5e692666c36eaeae9a441b6755/coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca", size = 240741, upload-time = "2025-05-23T11:39:36.252Z" }, 109 | { url = "https://files.pythonhosted.org/packages/e6/da/1c6ba2cf259710eed8916d4fd201dccc6be7380ad2b3b9f63ece3285d809/coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d", size = 238672, upload-time = "2025-05-23T11:39:38.03Z" }, 110 | { url = "https://files.pythonhosted.org/packages/ac/51/c8fae0dc3ca421e6e2509503696f910ff333258db672800c3bdef256265a/coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787", size = 239769, upload-time = "2025-05-23T11:39:40.24Z" }, 111 | { url = "https://files.pythonhosted.org/packages/59/8e/b97042ae92c59f40be0c989df090027377ba53f2d6cef73c9ca7685c26a6/coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7", size = 239555, upload-time = "2025-05-23T11:39:42.3Z" }, 112 | { url = "https://files.pythonhosted.org/packages/47/35/b8893e682d6e96b1db2af5997fc13ef62219426fb17259d6844c693c5e00/coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3", size = 237768, upload-time = "2025-05-23T11:39:44.069Z" }, 113 | { url = "https://files.pythonhosted.org/packages/03/6c/023b0b9a764cb52d6243a4591dcb53c4caf4d7340445113a1f452bb80591/coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7", size = 238757, upload-time = "2025-05-23T11:39:46.195Z" }, 114 | { url = "https://files.pythonhosted.org/packages/03/ed/3af7e4d721bd61a8df7de6de9e8a4271e67f3d9e086454558fd9f48eb4f6/coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a", size = 214166, upload-time = "2025-05-23T11:39:47.934Z" }, 115 | { url = "https://files.pythonhosted.org/packages/9d/30/ee774b626773750dc6128354884652507df3c59d6aa8431526107e595227/coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e", size = 215050, upload-time = "2025-05-23T11:39:50.252Z" }, 116 | { url = "https://files.pythonhosted.org/packages/69/2f/572b29496d8234e4a7773200dd835a0d32d9e171f2d974f3fe04a9dbc271/coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837", size = 203636, upload-time = "2025-05-23T11:39:52.002Z" }, 117 | { url = "https://files.pythonhosted.org/packages/a0/1a/0b9c32220ad694d66062f571cc5cedfa9997b64a591e8a500bb63de1bd40/coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32", size = 203623, upload-time = "2025-05-23T11:39:53.846Z" }, 118 | ] 119 | 120 | [package.optional-dependencies] 121 | toml = [ 122 | { name = "tomli", marker = "python_full_version <= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 123 | ] 124 | 125 | [[package]] 126 | name = "decorator" 127 | version = "5.2.1" 128 | source = { registry = "https://pypi.org/simple" } 129 | 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" } 130 | wheels = [ 131 | { 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" }, 132 | ] 133 | 134 | [[package]] 135 | name = "django" 136 | version = "4.2.22" 137 | source = { registry = "https://pypi.org/simple" } 138 | resolution-markers = [ 139 | "python_full_version < '3.10'", 140 | "python_full_version >= '3.11'", 141 | "python_full_version == '3.10.*'", 142 | ] 143 | dependencies = [ 144 | { name = "asgiref" }, 145 | { name = "sqlparse" }, 146 | { name = "tzdata", marker = "sys_platform == 'win32'" }, 147 | ] 148 | sdist = { url = "https://files.pythonhosted.org/packages/56/9e/37b909fa1c5e46ddb42ec37ec600a575d25dc47a6de86a1fce782a4a44ad/django-4.2.22.tar.gz", hash = "sha256:e726764b094407c313adba5e2e866ab88f00436cad85c540a5bf76dc0a912c9e", size = 10427236, upload-time = "2025-06-04T13:53:41.332Z" } 149 | wheels = [ 150 | { url = "https://files.pythonhosted.org/packages/dc/17/6afcbac3575992b22fda1ae7fffcdff15ff24d1aff69b3d36876bc0a47eb/django-4.2.22-py3-none-any.whl", hash = "sha256:0a32773b5b7f4e774a155ee253ab24a841fed7e9e9061db08bf2ce9711da404d", size = 7993908, upload-time = "2025-06-04T13:53:33.923Z" }, 151 | ] 152 | 153 | [[package]] 154 | name = "django" 155 | version = "5.0.14" 156 | source = { registry = "https://pypi.org/simple" } 157 | resolution-markers = [ 158 | "python_full_version >= '3.11'", 159 | "python_full_version == '3.10.*'", 160 | ] 161 | dependencies = [ 162 | { name = "asgiref", marker = "(python_full_version >= '3.10' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 163 | { name = "sqlparse", marker = "(python_full_version >= '3.10' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 164 | { name = "tzdata", marker = "(python_full_version >= '3.10' and sys_platform == 'win32' and extra == 'group-16-django-read-only-django50') or (python_full_version < '3.10' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (python_full_version < '3.10' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (python_full_version < '3.10' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra != 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 165 | ] 166 | sdist = { url = "https://files.pythonhosted.org/packages/9d/a4/cc0205045386b5be8eecb15a95f290383d103f0db5f7e34f93dcc340d5b0/Django-5.0.14.tar.gz", hash = "sha256:29019a5763dbd48da1720d687c3522ef40d1c61be6fb2fad27ed79e9f655bc11", size = 10644306, upload-time = "2025-04-02T11:24:41.396Z" } 167 | wheels = [ 168 | { url = "https://files.pythonhosted.org/packages/c0/93/eabde8789f41910845567ebbff5aacd52fd80e54c934ce15b83d5f552d2c/Django-5.0.14-py3-none-any.whl", hash = "sha256:e762bef8629ee704de215ebbd32062b84f4e56327eed412e5544f6f6eb1dfd74", size = 8185934, upload-time = "2025-04-02T11:24:36.888Z" }, 169 | ] 170 | 171 | [[package]] 172 | name = "django" 173 | version = "5.1.10" 174 | source = { registry = "https://pypi.org/simple" } 175 | resolution-markers = [ 176 | "python_full_version >= '3.11'", 177 | "python_full_version == '3.10.*'", 178 | ] 179 | dependencies = [ 180 | { name = "asgiref", marker = "(python_full_version >= '3.10' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52')" }, 181 | { name = "sqlparse", marker = "(python_full_version >= '3.10' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52')" }, 182 | { name = "tzdata", marker = "(python_full_version >= '3.10' and sys_platform == 'win32' and extra == 'group-16-django-read-only-django51') or (python_full_version < '3.10' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52')" }, 183 | ] 184 | sdist = { url = "https://files.pythonhosted.org/packages/73/ca/1c724be89e603eb8b5587ea24c63a8c30094c8ff4d990780b5033ee15c40/django-5.1.10.tar.gz", hash = "sha256:73e5d191421d177803dbd5495d94bc7d06d156df9561f4eea9e11b4994c07137", size = 10714538, upload-time = "2025-06-04T13:53:18.805Z" } 185 | wheels = [ 186 | { url = "https://files.pythonhosted.org/packages/9e/fc/80dc741ba0acb3241aac1213d7272c573d52d8a62ec2c69e9b3bef1547f2/django-5.1.10-py3-none-any.whl", hash = "sha256:19c9b771e9cf4de91101861aadd2daaa159bcf10698ca909c5755c88e70ccb84", size = 8277457, upload-time = "2025-06-04T13:53:07.676Z" }, 187 | ] 188 | 189 | [[package]] 190 | name = "django" 191 | version = "5.2.2" 192 | source = { registry = "https://pypi.org/simple" } 193 | resolution-markers = [ 194 | "python_full_version >= '3.11'", 195 | "python_full_version == '3.10.*'", 196 | ] 197 | dependencies = [ 198 | { name = "asgiref", marker = "python_full_version >= '3.10'" }, 199 | { name = "sqlparse", marker = "python_full_version >= '3.10'" }, 200 | { name = "tzdata", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, 201 | ] 202 | sdist = { url = "https://files.pythonhosted.org/packages/39/17/4567ee12bb84114c544d5c4a792e7226db517ac78f552111e9dc62d1de14/django-5.2.2.tar.gz", hash = "sha256:85852e517f84435e9b13421379cd6c43ef5b48a9c8b391d29a26f7900967e952", size = 10827542, upload-time = "2025-06-04T13:52:40.879Z" } 203 | wheels = [ 204 | { url = "https://files.pythonhosted.org/packages/b4/5c/5d00acab6c062b154e5a0f092938ae5a0c698dbc4362b68e23200960f32c/django-5.2.2-py3-none-any.whl", hash = "sha256:997ef2162d04ead6869551b22cde4e06da1f94cf595f4af3f3d3afeae1f3f6fe", size = 8302562, upload-time = "2025-06-04T13:52:33.14Z" }, 205 | ] 206 | 207 | [[package]] 208 | name = "django-read-only" 209 | version = "1.19.0" 210 | source = { editable = "." } 211 | dependencies = [ 212 | { name = "django", version = "4.2.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or extra == 'group-16-django-read-only-django42' or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 213 | { name = "django", version = "5.0.14", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 214 | { name = "django", version = "5.1.10", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52')" }, 215 | { name = "django", version = "5.2.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and extra != 'group-16-django-read-only-django42' and extra != 'group-16-django-read-only-django50' and extra != 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 216 | ] 217 | 218 | [package.dev-dependencies] 219 | django42 = [ 220 | { name = "django", version = "4.2.22", source = { registry = "https://pypi.org/simple" } }, 221 | ] 222 | django50 = [ 223 | { name = "django", version = "5.0.14", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, 224 | ] 225 | django51 = [ 226 | { name = "django", version = "5.1.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, 227 | ] 228 | django52 = [ 229 | { name = "django", version = "5.2.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, 230 | ] 231 | test = [ 232 | { name = "coverage", extra = ["toml"] }, 233 | { name = "ipython", version = "8.18.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 234 | { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 235 | { name = "ipython", version = "9.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 236 | { name = "psycopg", extra = ["binary"] }, 237 | { name = "pytest" }, 238 | { name = "pytest-django" }, 239 | { name = "pytest-randomly" }, 240 | ] 241 | 242 | [package.metadata] 243 | requires-dist = [{ name = "django", specifier = ">=4.2" }] 244 | 245 | [package.metadata.requires-dev] 246 | django42 = [{ name = "django", marker = "python_full_version >= '3.8'", specifier = ">=4.2a1,<5" }] 247 | django50 = [{ name = "django", marker = "python_full_version >= '3.10'", specifier = ">=5.0a1,<5.1" }] 248 | django51 = [{ name = "django", marker = "python_full_version >= '3.10'", specifier = ">=5.1a1,<5.2" }] 249 | django52 = [{ name = "django", marker = "python_full_version >= '3.10'", specifier = ">=5.2a1,<6" }] 250 | test = [ 251 | { name = "coverage", extras = ["toml"] }, 252 | { name = "ipython" }, 253 | { name = "psycopg", extras = ["binary"] }, 254 | { name = "pytest" }, 255 | { name = "pytest-django" }, 256 | { name = "pytest-randomly" }, 257 | ] 258 | 259 | [[package]] 260 | name = "exceptiongroup" 261 | version = "1.3.0" 262 | source = { registry = "https://pypi.org/simple" } 263 | dependencies = [ 264 | { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 265 | ] 266 | sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } 267 | wheels = [ 268 | { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, 269 | ] 270 | 271 | [[package]] 272 | name = "executing" 273 | version = "2.2.0" 274 | source = { registry = "https://pypi.org/simple" } 275 | sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693, upload-time = "2025-01-22T15:41:29.403Z" } 276 | wheels = [ 277 | { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" }, 278 | ] 279 | 280 | [[package]] 281 | name = "importlib-metadata" 282 | version = "8.7.0" 283 | source = { registry = "https://pypi.org/simple" } 284 | dependencies = [ 285 | { name = "zipp", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 286 | ] 287 | sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } 288 | wheels = [ 289 | { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, 290 | ] 291 | 292 | [[package]] 293 | name = "iniconfig" 294 | version = "2.1.0" 295 | source = { registry = "https://pypi.org/simple" } 296 | sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } 297 | wheels = [ 298 | { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, 299 | ] 300 | 301 | [[package]] 302 | name = "ipython" 303 | version = "8.18.1" 304 | source = { registry = "https://pypi.org/simple" } 305 | resolution-markers = [ 306 | "python_full_version < '3.10'", 307 | ] 308 | dependencies = [ 309 | { name = "colorama", marker = "(python_full_version < '3.10' and sys_platform == 'win32') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 310 | { name = "decorator", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 311 | { name = "exceptiongroup", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 312 | { name = "jedi", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 313 | { name = "matplotlib-inline", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 314 | { name = "pexpect", marker = "(python_full_version < '3.10' and sys_platform != 'win32') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (python_full_version >= '3.10' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 315 | { name = "prompt-toolkit", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 316 | { name = "pygments", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 317 | { name = "stack-data", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 318 | { name = "traitlets", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 319 | { name = "typing-extensions", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 320 | ] 321 | sdist = { url = "https://files.pythonhosted.org/packages/b1/b9/3ba6c45a6df813c09a48bac313c22ff83efa26cbb55011218d925a46e2ad/ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27", size = 5486330, upload-time = "2023-11-27T09:58:34.596Z" } 322 | wheels = [ 323 | { url = "https://files.pythonhosted.org/packages/47/6b/d9fdcdef2eb6a23f391251fde8781c38d42acd82abe84d054cb74f7863b0/ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397", size = 808161, upload-time = "2023-11-27T09:58:30.538Z" }, 324 | ] 325 | 326 | [[package]] 327 | name = "ipython" 328 | version = "8.37.0" 329 | source = { registry = "https://pypi.org/simple" } 330 | resolution-markers = [ 331 | "python_full_version == '3.10.*'", 332 | ] 333 | dependencies = [ 334 | { name = "colorama", marker = "(python_full_version == '3.10.*' and sys_platform == 'win32') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 335 | { name = "decorator", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 336 | { name = "exceptiongroup", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 337 | { name = "jedi", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 338 | { name = "matplotlib-inline", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 339 | { name = "pexpect", marker = "(python_full_version == '3.10.*' and sys_platform != 'emscripten' and sys_platform != 'win32') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (python_full_version != '3.10.*' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 340 | { name = "prompt-toolkit", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 341 | { name = "pygments", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 342 | { name = "stack-data", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 343 | { name = "traitlets", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 344 | { name = "typing-extensions", marker = "python_full_version == '3.10.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 345 | ] 346 | sdist = { url = "https://files.pythonhosted.org/packages/85/31/10ac88f3357fc276dc8a64e8880c82e80e7459326ae1d0a211b40abf6665/ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216", size = 5606088, upload-time = "2025-05-31T16:39:09.613Z" } 347 | wheels = [ 348 | { url = "https://files.pythonhosted.org/packages/91/d0/274fbf7b0b12643cbbc001ce13e6a5b1607ac4929d1b11c72460152c9fc3/ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2", size = 831864, upload-time = "2025-05-31T16:39:06.38Z" }, 349 | ] 350 | 351 | [[package]] 352 | name = "ipython" 353 | version = "9.3.0" 354 | source = { registry = "https://pypi.org/simple" } 355 | resolution-markers = [ 356 | "python_full_version >= '3.11'", 357 | ] 358 | dependencies = [ 359 | { name = "colorama", marker = "(python_full_version >= '3.11' and sys_platform == 'win32') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform != 'win32' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 360 | { name = "decorator", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 361 | { name = "ipython-pygments-lexers", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 362 | { name = "jedi", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 363 | { name = "matplotlib-inline", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 364 | { name = "pexpect", marker = "(python_full_version >= '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (python_full_version < '3.11' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'emscripten' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (sys_platform == 'win32' and extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 365 | { name = "prompt-toolkit", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 366 | { name = "pygments", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 367 | { name = "stack-data", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 368 | { name = "traitlets", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 369 | { name = "typing-extensions", marker = "python_full_version == '3.11.*' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 370 | ] 371 | sdist = { url = "https://files.pythonhosted.org/packages/dc/09/4c7e06b96fbd203e06567b60fb41b06db606b6a82db6db7b2c85bb72a15c/ipython-9.3.0.tar.gz", hash = "sha256:79eb896f9f23f50ad16c3bc205f686f6e030ad246cc309c6279a242b14afe9d8", size = 4426460, upload-time = "2025-05-31T16:34:55.678Z" } 372 | wheels = [ 373 | { url = "https://files.pythonhosted.org/packages/3c/99/9ed3d52d00f1846679e3aa12e2326ac7044b5e7f90dc822b60115fa533ca/ipython-9.3.0-py3-none-any.whl", hash = "sha256:1a0b6dd9221a1f5dddf725b57ac0cb6fddc7b5f470576231ae9162b9b3455a04", size = 605320, upload-time = "2025-05-31T16:34:52.154Z" }, 374 | ] 375 | 376 | [[package]] 377 | name = "ipython-pygments-lexers" 378 | version = "1.1.1" 379 | source = { registry = "https://pypi.org/simple" } 380 | dependencies = [ 381 | { name = "pygments", marker = "python_full_version >= '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 382 | ] 383 | 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" } 384 | wheels = [ 385 | { 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" }, 386 | ] 387 | 388 | [[package]] 389 | name = "jedi" 390 | version = "0.19.2" 391 | source = { registry = "https://pypi.org/simple" } 392 | dependencies = [ 393 | { name = "parso" }, 394 | ] 395 | 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" } 396 | wheels = [ 397 | { 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" }, 398 | ] 399 | 400 | [[package]] 401 | name = "matplotlib-inline" 402 | version = "0.1.7" 403 | source = { registry = "https://pypi.org/simple" } 404 | dependencies = [ 405 | { name = "traitlets" }, 406 | ] 407 | sdist = { url = "https://files.pythonhosted.org/packages/99/5b/a36a337438a14116b16480db471ad061c36c3694df7c2084a0da7ba538b7/matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", size = 8159, upload-time = "2024-04-15T13:44:44.803Z" } 408 | wheels = [ 409 | { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899, upload-time = "2024-04-15T13:44:43.265Z" }, 410 | ] 411 | 412 | [[package]] 413 | name = "packaging" 414 | version = "25.0" 415 | source = { registry = "https://pypi.org/simple" } 416 | 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" } 417 | wheels = [ 418 | { 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" }, 419 | ] 420 | 421 | [[package]] 422 | name = "parso" 423 | version = "0.8.4" 424 | source = { registry = "https://pypi.org/simple" } 425 | sdist = { url = "https://files.pythonhosted.org/packages/66/94/68e2e17afaa9169cf6412ab0f28623903be73d1b32e208d9e8e541bb086d/parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d", size = 400609, upload-time = "2024-04-05T09:43:55.897Z" } 426 | wheels = [ 427 | { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650, upload-time = "2024-04-05T09:43:53.299Z" }, 428 | ] 429 | 430 | [[package]] 431 | name = "pexpect" 432 | version = "4.9.0" 433 | source = { registry = "https://pypi.org/simple" } 434 | dependencies = [ 435 | { name = "ptyprocess" }, 436 | ] 437 | 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" } 438 | wheels = [ 439 | { 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" }, 440 | ] 441 | 442 | [[package]] 443 | name = "pluggy" 444 | version = "1.6.0" 445 | source = { registry = "https://pypi.org/simple" } 446 | 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" } 447 | wheels = [ 448 | { 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" }, 449 | ] 450 | 451 | [[package]] 452 | name = "prompt-toolkit" 453 | version = "3.0.51" 454 | source = { registry = "https://pypi.org/simple" } 455 | dependencies = [ 456 | { name = "wcwidth" }, 457 | ] 458 | sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" } 459 | wheels = [ 460 | { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, 461 | ] 462 | 463 | [[package]] 464 | name = "psycopg" 465 | version = "3.2.9" 466 | source = { registry = "https://pypi.org/simple" } 467 | dependencies = [ 468 | { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 469 | { name = "tzdata", marker = "sys_platform == 'win32' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 470 | ] 471 | sdist = { url = "https://files.pythonhosted.org/packages/27/4a/93a6ab570a8d1a4ad171a1f4256e205ce48d828781312c0bbaff36380ecb/psycopg-3.2.9.tar.gz", hash = "sha256:2fbb46fcd17bc81f993f28c47f1ebea38d66ae97cc2dbc3cad73b37cefbff700", size = 158122, upload-time = "2025-05-13T16:11:15.533Z" } 472 | wheels = [ 473 | { url = "https://files.pythonhosted.org/packages/44/b0/a73c195a56eb6b92e937a5ca58521a5c3346fb233345adc80fd3e2f542e2/psycopg-3.2.9-py3-none-any.whl", hash = "sha256:01a8dadccdaac2123c916208c96e06631641c0566b22005493f09663c7a8d3b6", size = 202705, upload-time = "2025-05-13T16:06:26.584Z" }, 474 | ] 475 | 476 | [package.optional-dependencies] 477 | binary = [ 478 | { name = "psycopg-binary", marker = "implementation_name != 'pypy' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 479 | ] 480 | 481 | [[package]] 482 | name = "psycopg-binary" 483 | version = "3.2.9" 484 | source = { registry = "https://pypi.org/simple" } 485 | wheels = [ 486 | { url = "https://files.pythonhosted.org/packages/b6/ce/d677bc51f9b180986e5515268603519cee682eb6b5e765ae46cdb8526579/psycopg_binary-3.2.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:528239bbf55728ba0eacbd20632342867590273a9bacedac7538ebff890f1093", size = 4033081, upload-time = "2025-05-13T16:06:29.666Z" }, 487 | { url = "https://files.pythonhosted.org/packages/de/f4/b56263eb20dc36d71d7188622872098400536928edf86895736e28546b3c/psycopg_binary-3.2.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4978c01ca4c208c9d6376bd585e2c0771986b76ff7ea518f6d2b51faece75e8", size = 4082141, upload-time = "2025-05-13T16:06:33.81Z" }, 488 | { url = "https://files.pythonhosted.org/packages/68/47/5316c3b0a2b1ff5f1d440a27638250569994534874a2ce88bf24f5c51c0f/psycopg_binary-3.2.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ed2bab85b505d13e66a914d0f8cdfa9475c16d3491cf81394e0748b77729af2", size = 4678993, upload-time = "2025-05-13T16:06:36.309Z" }, 489 | { url = "https://files.pythonhosted.org/packages/53/24/b2c667b59f07fd7d7805c0c2074351bf2b98a336c5030d961db316512ffb/psycopg_binary-3.2.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:799fa1179ab8a58d1557a95df28b492874c8f4135101b55133ec9c55fc9ae9d7", size = 4500117, upload-time = "2025-05-13T16:06:38.847Z" }, 490 | { url = "https://files.pythonhosted.org/packages/ae/91/a08f8878b0fe0b34b083c149df950bce168bc1b18b2fe849fa42bf4378d4/psycopg_binary-3.2.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb37ac3955d19e4996c3534abfa4f23181333974963826db9e0f00731274b695", size = 4766985, upload-time = "2025-05-13T16:06:42.502Z" }, 491 | { url = "https://files.pythonhosted.org/packages/10/be/3a45d5b7d8f4c4332fd42465f2170b5aef4d28a7c79e79ac7e5e1dac74d7/psycopg_binary-3.2.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:001e986656f7e06c273dd4104e27f4b4e0614092e544d950c7c938d822b1a894", size = 4461990, upload-time = "2025-05-13T16:06:45.971Z" }, 492 | { url = "https://files.pythonhosted.org/packages/03/ce/20682b9a4fc270d8dc644a0b16c1978732146c6ff0abbc48fbab2f4a70aa/psycopg_binary-3.2.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fa5c80d8b4cbf23f338db88a7251cef8bb4b68e0f91cf8b6ddfa93884fdbb0c1", size = 3777947, upload-time = "2025-05-13T16:06:49.134Z" }, 493 | { url = "https://files.pythonhosted.org/packages/07/5c/f6d486e00bcd8709908ccdd436b2a190d390dfd61e318de4060bc6ee2a1e/psycopg_binary-3.2.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:39a127e0cf9b55bd4734a8008adf3e01d1fd1cb36339c6a9e2b2cbb6007c50ee", size = 3337502, upload-time = "2025-05-13T16:06:51.378Z" }, 494 | { url = "https://files.pythonhosted.org/packages/0b/a1/086508e929c0123a7f532840bb0a0c8a1ebd7e06aef3ee7fa44a3589bcdf/psycopg_binary-3.2.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fb7599e436b586e265bea956751453ad32eb98be6a6e694252f4691c31b16edb", size = 3440809, upload-time = "2025-05-13T16:06:54.552Z" }, 495 | { url = "https://files.pythonhosted.org/packages/40/f2/3a347a0f894355a6b173fca2202eca279b6197727b24e4896cf83f4263ee/psycopg_binary-3.2.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5d2c9fe14fe42b3575a0b4e09b081713e83b762c8dc38a3771dd3265f8f110e7", size = 3497231, upload-time = "2025-05-13T16:06:58.858Z" }, 496 | { url = "https://files.pythonhosted.org/packages/18/31/0845a385eb6f4521b398793293b5f746a101e80d5c43792990442d26bc2e/psycopg_binary-3.2.9-cp310-cp310-win_amd64.whl", hash = "sha256:7e4660fad2807612bb200de7262c88773c3483e85d981324b3c647176e41fdc8", size = 2936845, upload-time = "2025-05-13T16:07:02.712Z" }, 497 | { url = "https://files.pythonhosted.org/packages/b6/84/259ea58aca48e03c3c793b4ccfe39ed63db7b8081ef784d039330d9eed96/psycopg_binary-3.2.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2504e9fd94eabe545d20cddcc2ff0da86ee55d76329e1ab92ecfcc6c0a8156c4", size = 4040785, upload-time = "2025-05-13T16:07:07.569Z" }, 498 | { url = "https://files.pythonhosted.org/packages/25/22/ce58ffda2b7e36e45042b4d67f1bbd4dd2ccf4cfd2649696685c61046475/psycopg_binary-3.2.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:093a0c079dd6228a7f3c3d82b906b41964eaa062a9a8c19f45ab4984bf4e872b", size = 4087601, upload-time = "2025-05-13T16:07:11.75Z" }, 499 | { url = "https://files.pythonhosted.org/packages/c6/4f/b043e85268650c245025e80039b79663d8986f857bc3d3a72b1de67f3550/psycopg_binary-3.2.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:387c87b51d72442708e7a853e7e7642717e704d59571da2f3b29e748be58c78a", size = 4676524, upload-time = "2025-05-13T16:07:17.038Z" }, 500 | { url = "https://files.pythonhosted.org/packages/da/29/7afbfbd3740ea52fda488db190ef2ef2a9ff7379b85501a2142fb9f7dd56/psycopg_binary-3.2.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9ac10a2ebe93a102a326415b330fff7512f01a9401406896e78a81d75d6eddc", size = 4495671, upload-time = "2025-05-13T16:07:21.709Z" }, 501 | { url = "https://files.pythonhosted.org/packages/ea/eb/df69112d18a938cbb74efa1573082248437fa663ba66baf2cdba8a95a2d0/psycopg_binary-3.2.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72fdbda5b4c2a6a72320857ef503a6589f56d46821592d4377c8c8604810342b", size = 4768132, upload-time = "2025-05-13T16:07:25.818Z" }, 502 | { url = "https://files.pythonhosted.org/packages/76/fe/4803b20220c04f508f50afee9169268553f46d6eed99640a08c8c1e76409/psycopg_binary-3.2.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f34e88940833d46108f949fdc1fcfb74d6b5ae076550cd67ab59ef47555dba95", size = 4458394, upload-time = "2025-05-13T16:07:29.148Z" }, 503 | { url = "https://files.pythonhosted.org/packages/0f/0f/5ecc64607ef6f62b04e610b7837b1a802ca6f7cb7211339f5d166d55f1dd/psycopg_binary-3.2.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a3e0f89fe35cb03ff1646ab663dabf496477bab2a072315192dbaa6928862891", size = 3776879, upload-time = "2025-05-13T16:07:32.503Z" }, 504 | { url = "https://files.pythonhosted.org/packages/c8/d8/1c3d6e99b7db67946d0eac2cd15d10a79aa7b1e3222ce4aa8e7df72027f5/psycopg_binary-3.2.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6afb3e62f2a3456f2180a4eef6b03177788df7ce938036ff7f09b696d418d186", size = 3333329, upload-time = "2025-05-13T16:07:35.555Z" }, 505 | { url = "https://files.pythonhosted.org/packages/d7/02/a4e82099816559f558ccaf2b6945097973624dc58d5d1c91eb1e54e5a8e9/psycopg_binary-3.2.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:cc19ed5c7afca3f6b298bfc35a6baa27adb2019670d15c32d0bb8f780f7d560d", size = 3435683, upload-time = "2025-05-13T16:07:37.863Z" }, 506 | { url = "https://files.pythonhosted.org/packages/91/e4/f27055290d58e8818bed8a297162a096ef7f8ecdf01d98772d4b02af46c4/psycopg_binary-3.2.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bc75f63653ce4ec764c8f8c8b0ad9423e23021e1c34a84eb5f4ecac8538a4a4a", size = 3497124, upload-time = "2025-05-13T16:07:40.567Z" }, 507 | { url = "https://files.pythonhosted.org/packages/67/3d/17ed07579625529534605eeaeba34f0536754a5667dbf20ea2624fc80614/psycopg_binary-3.2.9-cp311-cp311-win_amd64.whl", hash = "sha256:3db3ba3c470801e94836ad78bf11fd5fab22e71b0c77343a1ee95d693879937a", size = 2939520, upload-time = "2025-05-13T16:07:45.467Z" }, 508 | { url = "https://files.pythonhosted.org/packages/29/6f/ec9957e37a606cd7564412e03f41f1b3c3637a5be018d0849914cb06e674/psycopg_binary-3.2.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:be7d650a434921a6b1ebe3fff324dbc2364393eb29d7672e638ce3e21076974e", size = 4022205, upload-time = "2025-05-13T16:07:48.195Z" }, 509 | { url = "https://files.pythonhosted.org/packages/6b/ba/497b8bea72b20a862ac95a94386967b745a472d9ddc88bc3f32d5d5f0d43/psycopg_binary-3.2.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6a76b4722a529390683c0304501f238b365a46b1e5fb6b7249dbc0ad6fea51a0", size = 4083795, upload-time = "2025-05-13T16:07:50.917Z" }, 510 | { url = "https://files.pythonhosted.org/packages/42/07/af9503e8e8bdad3911fd88e10e6a29240f9feaa99f57d6fac4a18b16f5a0/psycopg_binary-3.2.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96a551e4683f1c307cfc3d9a05fec62c00a7264f320c9962a67a543e3ce0d8ff", size = 4655043, upload-time = "2025-05-13T16:07:54.857Z" }, 511 | { url = "https://files.pythonhosted.org/packages/28/ed/aff8c9850df1648cc6a5cc7a381f11ee78d98a6b807edd4a5ae276ad60ad/psycopg_binary-3.2.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:61d0a6ceed8f08c75a395bc28cb648a81cf8dee75ba4650093ad1a24a51c8724", size = 4477972, upload-time = "2025-05-13T16:07:57.925Z" }, 512 | { url = "https://files.pythonhosted.org/packages/5c/bd/8e9d1b77ec1a632818fe2f457c3a65af83c68710c4c162d6866947d08cc5/psycopg_binary-3.2.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad280bbd409bf598683dda82232f5215cfc5f2b1bf0854e409b4d0c44a113b1d", size = 4737516, upload-time = "2025-05-13T16:08:01.616Z" }, 513 | { url = "https://files.pythonhosted.org/packages/46/ec/222238f774cd5a0881f3f3b18fb86daceae89cc410f91ef6a9fb4556f236/psycopg_binary-3.2.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76eddaf7fef1d0994e3d536ad48aa75034663d3a07f6f7e3e601105ae73aeff6", size = 4436160, upload-time = "2025-05-13T16:08:04.278Z" }, 514 | { url = "https://files.pythonhosted.org/packages/37/78/af5af2a1b296eeca54ea7592cd19284739a844974c9747e516707e7b3b39/psycopg_binary-3.2.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:52e239cd66c4158e412318fbe028cd94b0ef21b0707f56dcb4bdc250ee58fd40", size = 3753518, upload-time = "2025-05-13T16:08:07.567Z" }, 515 | { url = "https://files.pythonhosted.org/packages/ec/ac/8a3ed39ea069402e9e6e6a2f79d81a71879708b31cc3454283314994b1ae/psycopg_binary-3.2.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:08bf9d5eabba160dd4f6ad247cf12f229cc19d2458511cab2eb9647f42fa6795", size = 3313598, upload-time = "2025-05-13T16:08:09.999Z" }, 516 | { url = "https://files.pythonhosted.org/packages/da/43/26549af068347c808fbfe5f07d2fa8cef747cfff7c695136172991d2378b/psycopg_binary-3.2.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1b2cf018168cad87580e67bdde38ff5e51511112f1ce6ce9a8336871f465c19a", size = 3407289, upload-time = "2025-05-13T16:08:12.66Z" }, 517 | { url = "https://files.pythonhosted.org/packages/67/55/ea8d227c77df8e8aec880ded398316735add8fda5eb4ff5cc96fac11e964/psycopg_binary-3.2.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:14f64d1ac6942ff089fc7e926440f7a5ced062e2ed0949d7d2d680dc5c00e2d4", size = 3472493, upload-time = "2025-05-13T16:08:15.672Z" }, 518 | { url = "https://files.pythonhosted.org/packages/3c/02/6ff2a5bc53c3cd653d281666728e29121149179c73fddefb1e437024c192/psycopg_binary-3.2.9-cp312-cp312-win_amd64.whl", hash = "sha256:7a838852e5afb6b4126f93eb409516a8c02a49b788f4df8b6469a40c2157fa21", size = 2927400, upload-time = "2025-05-13T16:08:18.652Z" }, 519 | { url = "https://files.pythonhosted.org/packages/28/0b/f61ff4e9f23396aca674ed4d5c9a5b7323738021d5d72d36d8b865b3deaf/psycopg_binary-3.2.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:98bbe35b5ad24a782c7bf267596638d78aa0e87abc7837bdac5b2a2ab954179e", size = 4017127, upload-time = "2025-05-13T16:08:21.391Z" }, 520 | { url = "https://files.pythonhosted.org/packages/bc/00/7e181fb1179fbfc24493738b61efd0453d4b70a0c4b12728e2b82db355fd/psycopg_binary-3.2.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:72691a1615ebb42da8b636c5ca9f2b71f266be9e172f66209a361c175b7842c5", size = 4080322, upload-time = "2025-05-13T16:08:24.049Z" }, 521 | { url = "https://files.pythonhosted.org/packages/58/fd/94fc267c1d1392c4211e54ccb943be96ea4032e761573cf1047951887494/psycopg_binary-3.2.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25ab464bfba8c401f5536d5aa95f0ca1dd8257b5202eede04019b4415f491351", size = 4655097, upload-time = "2025-05-13T16:08:27.376Z" }, 522 | { url = "https://files.pythonhosted.org/packages/41/17/31b3acf43de0b2ba83eac5878ff0dea5a608ca2a5c5dd48067999503a9de/psycopg_binary-3.2.9-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e8aeefebe752f46e3c4b769e53f1d4ad71208fe1150975ef7662c22cca80fab", size = 4482114, upload-time = "2025-05-13T16:08:30.781Z" }, 523 | { url = "https://files.pythonhosted.org/packages/85/78/b4d75e5fd5a85e17f2beb977abbba3389d11a4536b116205846b0e1cf744/psycopg_binary-3.2.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7e4e4dd177a8665c9ce86bc9caae2ab3aa9360b7ce7ec01827ea1baea9ff748", size = 4737693, upload-time = "2025-05-13T16:08:34.625Z" }, 524 | { url = "https://files.pythonhosted.org/packages/3b/95/7325a8550e3388b00b5e54f4ced5e7346b531eb4573bf054c3dbbfdc14fe/psycopg_binary-3.2.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fc2915949e5c1ea27a851f7a472a7da7d0a40d679f0a31e42f1022f3c562e87", size = 4437423, upload-time = "2025-05-13T16:08:37.444Z" }, 525 | { url = "https://files.pythonhosted.org/packages/1a/db/cef77d08e59910d483df4ee6da8af51c03bb597f500f1fe818f0f3b925d3/psycopg_binary-3.2.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a1fa38a4687b14f517f049477178093c39c2a10fdcced21116f47c017516498f", size = 3758667, upload-time = "2025-05-13T16:08:40.116Z" }, 526 | { url = "https://files.pythonhosted.org/packages/95/3e/252fcbffb47189aa84d723b54682e1bb6d05c8875fa50ce1ada914ae6e28/psycopg_binary-3.2.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5be8292d07a3ab828dc95b5ee6b69ca0a5b2e579a577b39671f4f5b47116dfd2", size = 3320576, upload-time = "2025-05-13T16:08:43.243Z" }, 527 | { url = "https://files.pythonhosted.org/packages/1c/cd/9b5583936515d085a1bec32b45289ceb53b80d9ce1cea0fef4c782dc41a7/psycopg_binary-3.2.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:778588ca9897b6c6bab39b0d3034efff4c5438f5e3bd52fda3914175498202f9", size = 3411439, upload-time = "2025-05-13T16:08:47.321Z" }, 528 | { url = "https://files.pythonhosted.org/packages/45/6b/6f1164ea1634c87956cdb6db759e0b8c5827f989ee3cdff0f5c70e8331f2/psycopg_binary-3.2.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f0d5b3af045a187aedbd7ed5fc513bd933a97aaff78e61c3745b330792c4345b", size = 3477477, upload-time = "2025-05-13T16:08:51.166Z" }, 529 | { url = "https://files.pythonhosted.org/packages/7b/1d/bf54cfec79377929da600c16114f0da77a5f1670f45e0c3af9fcd36879bc/psycopg_binary-3.2.9-cp313-cp313-win_amd64.whl", hash = "sha256:2290bc146a1b6a9730350f695e8b670e1d1feb8446597bed0bbe7c3c30e0abcb", size = 2928009, upload-time = "2025-05-13T16:08:53.67Z" }, 530 | { url = "https://files.pythonhosted.org/packages/0b/4a/e095884dd016b2bde2796043c61cd383b79e5d2a820c33e2c47293707ca8/psycopg_binary-3.2.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587a3f19954d687a14e0c8202628844db692dbf00bba0e6d006659bf1ca91cbe", size = 4034274, upload-time = "2025-05-13T16:09:43.738Z" }, 531 | { url = "https://files.pythonhosted.org/packages/11/e9/ab3fad6033de260a620f6481e66092417ce31fa194dbf9ac292ab8cb9fd0/psycopg_binary-3.2.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:791759138380df21d356ff991265fde7fe5997b0c924a502847a9f9141e68786", size = 4083015, upload-time = "2025-05-13T16:09:54.896Z" }, 532 | { url = "https://files.pythonhosted.org/packages/ba/c8/6cd54a349d0b62b080761eb7bda43190003ecbbf17920d57254d5c780e11/psycopg_binary-3.2.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95315b8c8ddfa2fdcb7fe3ddea8a595c1364524f512160c604e3be368be9dd07", size = 4679369, upload-time = "2025-05-13T16:10:00.545Z" }, 533 | { url = "https://files.pythonhosted.org/packages/51/34/35c65ac413c485e9340d62f14adcb34420acae44425f77aee591d49e6647/psycopg_binary-3.2.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18ac08475c9b971237fcc395b0a6ee4e8580bb5cf6247bc9b8461644bef5d9f4", size = 4500889, upload-time = "2025-05-13T16:10:07.593Z" }, 534 | { url = "https://files.pythonhosted.org/packages/77/a9/f691b8037b0bcef481b09ae4283beedbf048f79b6fe9bda1445dbb14ed18/psycopg_binary-3.2.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac2c04b6345e215e65ca6aef5c05cc689a960b16674eaa1f90a8f86dfaee8c04", size = 4769218, upload-time = "2025-05-13T16:10:23.076Z" }, 535 | { url = "https://files.pythonhosted.org/packages/ee/38/25afc811c1dfb664b31d66d6f5c070326a1f89f768f1b673273a3abe6912/psycopg_binary-3.2.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1ab25e3134774f1e476d4bb9050cdec25f10802e63e92153906ae934578734", size = 4462834, upload-time = "2025-05-13T16:10:30.442Z" }, 536 | { url = "https://files.pythonhosted.org/packages/df/e2/eb4a8230e13f691d6e386e22b16d4b90f454839b78ac547be3f399562ee4/psycopg_binary-3.2.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4bfec4a73e8447d8fe8854886ffa78df2b1c279a7592241c2eb393d4499a17e2", size = 3779527, upload-time = "2025-05-13T16:10:42.705Z" }, 537 | { url = "https://files.pythonhosted.org/packages/26/39/0f79c7d42f0c5711861ce9db55c65e14e7f1e52bd40304b4d6e7cd505e61/psycopg_binary-3.2.9-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:166acc57af5d2ff0c0c342aed02e69a0cd5ff216cae8820c1059a6f3b7cf5f78", size = 3337958, upload-time = "2025-05-13T16:10:47.874Z" }, 538 | { url = "https://files.pythonhosted.org/packages/11/ce/28b1d98aed9337a721b271778d07c5ac7f85730d96f0185cc6d22684536d/psycopg_binary-3.2.9-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:413f9e46259fe26d99461af8e1a2b4795a4e27cc8ac6f7919ec19bcee8945074", size = 3440567, upload-time = "2025-05-13T16:10:57.821Z" }, 539 | { url = "https://files.pythonhosted.org/packages/24/54/40a3a8175566f8c1268af0bacf5d7b26371697b6cefa87352c1df4b435e1/psycopg_binary-3.2.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:354dea21137a316b6868ee41c2ae7cce001e104760cf4eab3ec85627aed9b6cd", size = 3498637, upload-time = "2025-05-13T16:11:02.854Z" }, 540 | { url = "https://files.pythonhosted.org/packages/63/ee/51748bc8af0ba08e7415fcbbd00b7d069c068f8c08509e8dd0dd0a066394/psycopg_binary-3.2.9-cp39-cp39-win_amd64.whl", hash = "sha256:24ddb03c1ccfe12d000d950c9aba93a7297993c4e3905d9f2c9795bb0764d523", size = 2938614, upload-time = "2025-05-13T16:11:13.299Z" }, 541 | ] 542 | 543 | [[package]] 544 | name = "ptyprocess" 545 | version = "0.7.0" 546 | source = { registry = "https://pypi.org/simple" } 547 | 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" } 548 | wheels = [ 549 | { 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" }, 550 | ] 551 | 552 | [[package]] 553 | name = "pure-eval" 554 | version = "0.2.3" 555 | source = { registry = "https://pypi.org/simple" } 556 | 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" } 557 | wheels = [ 558 | { 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" }, 559 | ] 560 | 561 | [[package]] 562 | name = "pygments" 563 | version = "2.19.1" 564 | source = { registry = "https://pypi.org/simple" } 565 | sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } 566 | wheels = [ 567 | { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, 568 | ] 569 | 570 | [[package]] 571 | name = "pytest" 572 | version = "8.4.0" 573 | source = { registry = "https://pypi.org/simple" } 574 | dependencies = [ 575 | { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 576 | { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 577 | { name = "iniconfig" }, 578 | { name = "packaging" }, 579 | { name = "pluggy" }, 580 | { name = "pygments" }, 581 | { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 582 | ] 583 | sdist = { url = "https://files.pythonhosted.org/packages/fb/aa/405082ce2749be5398045152251ac69c0f3578c7077efc53431303af97ce/pytest-8.4.0.tar.gz", hash = "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6", size = 1515232, upload-time = "2025-06-02T17:36:30.03Z" } 584 | wheels = [ 585 | { url = "https://files.pythonhosted.org/packages/2f/de/afa024cbe022b1b318a3d224125aa24939e99b4ff6f22e0ba639a2eaee47/pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e", size = 363797, upload-time = "2025-06-02T17:36:27.859Z" }, 586 | ] 587 | 588 | [[package]] 589 | name = "pytest-django" 590 | version = "4.11.1" 591 | source = { registry = "https://pypi.org/simple" } 592 | dependencies = [ 593 | { name = "pytest" }, 594 | ] 595 | sdist = { url = "https://files.pythonhosted.org/packages/b1/fb/55d580352db26eb3d59ad50c64321ddfe228d3d8ac107db05387a2fadf3a/pytest_django-4.11.1.tar.gz", hash = "sha256:a949141a1ee103cb0e7a20f1451d355f83f5e4a5d07bdd4dcfdd1fd0ff227991", size = 86202, upload-time = "2025-04-03T18:56:09.338Z" } 596 | wheels = [ 597 | { url = "https://files.pythonhosted.org/packages/be/ac/bd0608d229ec808e51a21044f3f2f27b9a37e7a0ebaca7247882e67876af/pytest_django-4.11.1-py3-none-any.whl", hash = "sha256:1b63773f648aa3d8541000c26929c1ea63934be1cfa674c76436966d73fe6a10", size = 25281, upload-time = "2025-04-03T18:56:07.678Z" }, 598 | ] 599 | 600 | [[package]] 601 | name = "pytest-randomly" 602 | version = "3.16.0" 603 | source = { registry = "https://pypi.org/simple" } 604 | dependencies = [ 605 | { name = "importlib-metadata", marker = "python_full_version < '3.10' or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django50') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django42' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django51') or (extra == 'group-16-django-read-only-django50' and extra == 'group-16-django-read-only-django52') or (extra == 'group-16-django-read-only-django51' and extra == 'group-16-django-read-only-django52')" }, 606 | { name = "pytest" }, 607 | ] 608 | sdist = { url = "https://files.pythonhosted.org/packages/c0/68/d221ed7f4a2a49a664da721b8e87b52af6dd317af2a6cb51549cf17ac4b8/pytest_randomly-3.16.0.tar.gz", hash = "sha256:11bf4d23a26484de7860d82f726c0629837cf4064b79157bd18ec9d41d7feb26", size = 13367, upload-time = "2024-10-25T15:45:34.274Z" } 609 | wheels = [ 610 | { url = "https://files.pythonhosted.org/packages/22/70/b31577d7c46d8e2f9baccfed5067dd8475262a2331ffb0bfdf19361c9bde/pytest_randomly-3.16.0-py3-none-any.whl", hash = "sha256:8633d332635a1a0983d3bba19342196807f6afb17c3eef78e02c2f85dade45d6", size = 8396, upload-time = "2024-10-25T15:45:32.78Z" }, 611 | ] 612 | 613 | [[package]] 614 | name = "sqlparse" 615 | version = "0.5.3" 616 | source = { registry = "https://pypi.org/simple" } 617 | sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999, upload-time = "2024-12-10T12:05:30.728Z" } 618 | wheels = [ 619 | { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415, upload-time = "2024-12-10T12:05:27.824Z" }, 620 | ] 621 | 622 | [[package]] 623 | name = "stack-data" 624 | version = "0.6.3" 625 | source = { registry = "https://pypi.org/simple" } 626 | dependencies = [ 627 | { name = "asttokens" }, 628 | { name = "executing" }, 629 | { name = "pure-eval" }, 630 | ] 631 | 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" } 632 | wheels = [ 633 | { 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" }, 634 | ] 635 | 636 | [[package]] 637 | name = "tomli" 638 | version = "2.2.1" 639 | source = { registry = "https://pypi.org/simple" } 640 | sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } 641 | wheels = [ 642 | { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, 643 | { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, 644 | { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, 645 | { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, 646 | { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, 647 | { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, 648 | { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, 649 | { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, 650 | { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, 651 | { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, 652 | { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, 653 | { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, 654 | { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, 655 | { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, 656 | { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, 657 | { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, 658 | { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, 659 | { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, 660 | { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, 661 | { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, 662 | { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, 663 | { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, 664 | { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, 665 | { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, 666 | { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, 667 | { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, 668 | { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, 669 | { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, 670 | { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, 671 | { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, 672 | { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, 673 | ] 674 | 675 | [[package]] 676 | name = "traitlets" 677 | version = "5.14.3" 678 | source = { registry = "https://pypi.org/simple" } 679 | 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" } 680 | wheels = [ 681 | { 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" }, 682 | ] 683 | 684 | [[package]] 685 | name = "typing-extensions" 686 | version = "4.14.0" 687 | source = { registry = "https://pypi.org/simple" } 688 | sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" } 689 | wheels = [ 690 | { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, 691 | ] 692 | 693 | [[package]] 694 | name = "tzdata" 695 | version = "2025.2" 696 | source = { registry = "https://pypi.org/simple" } 697 | sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } 698 | wheels = [ 699 | { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, 700 | ] 701 | 702 | [[package]] 703 | name = "wcwidth" 704 | version = "0.2.13" 705 | source = { registry = "https://pypi.org/simple" } 706 | sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" } 707 | wheels = [ 708 | { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, 709 | ] 710 | 711 | [[package]] 712 | name = "zipp" 713 | version = "3.22.0" 714 | source = { registry = "https://pypi.org/simple" } 715 | sdist = { url = "https://files.pythonhosted.org/packages/12/b6/7b3d16792fdf94f146bed92be90b4eb4563569eca91513c8609aebf0c167/zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5", size = 25257, upload-time = "2025-05-26T14:46:32.217Z" } 716 | wheels = [ 717 | { url = "https://files.pythonhosted.org/packages/ad/da/f64669af4cae46f17b90798a827519ce3737d31dbafad65d391e49643dc4/zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343", size = 9796, upload-time = "2025-05-26T14:46:30.775Z" }, 718 | ] 719 | --------------------------------------------------------------------------------