diff --git a/.github/contributors.json b/.github/contributors.json index 78d93669c3..0751ef056b 100644 --- a/.github/contributors.json +++ b/.github/contributors.json @@ -1664,5 +1664,25 @@ "name": "Christian Jensen", "github_login": "jensenbox", "twitter_username": "cjensen" + }, + { + "name": "Denis Darii", + "github_login": "DNX", + "twitter_username": "" + }, + { + "name": "qwerrrqw", + "github_login": "qwerrrqw", + "twitter_username": "" + }, + { + "name": "Pulse-Mind", + "github_login": "pulse-mind", + "twitter_username": "" + }, + { + "name": "Hana Belay", + "github_login": "earthcomfy", + "twitter_username": "" } ] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44e31e598c..dd22fb512f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,9 +24,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: "true" + uses: astral-sh/setup-uv@v5 - name: Install dependencies run: uv sync - name: Run tests @@ -55,9 +53,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: "true" + uses: astral-sh/setup-uv@v5 - name: Install dependencies run: uv sync - name: Docker ${{ matrix.script.name }} @@ -102,13 +98,11 @@ jobs: with: python-version: "3.12" - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: "true" + uses: astral-sh/setup-uv@v5 - name: Install dependencies run: uv sync - uses: actions/setup-node@v4 with: - node-version: "22" + node-version: "22.13" - name: Bare Metal ${{ matrix.script.name }} run: sh tests/test_bare.sh ${{ matrix.script.args }} diff --git a/.github/workflows/dependabot-uv-lock.yml b/.github/workflows/dependabot-uv-lock.yml index 73fb88130c..5a2b5593dc 100644 --- a/.github/workflows/dependabot-uv-lock.yml +++ b/.github/workflows/dependabot-uv-lock.yml @@ -26,9 +26,7 @@ jobs: uses: actions/checkout@v4 if: ${{ env.GH_PAT == '' }} - - uses: astral-sh/setup-uv@v3 - with: - enable-cache: true + - uses: astral-sh/setup-uv@v5 - run: uv lock - uses: stefanzweifel/git-auto-commit-action@v5 with: diff --git a/.github/workflows/django-issue-checker.yml b/.github/workflows/django-issue-checker.yml index 1d6de43323..d0a3c2709e 100644 --- a/.github/workflows/django-issue-checker.yml +++ b/.github/workflows/django-issue-checker.yml @@ -18,9 +18,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: "true" + uses: astral-sh/setup-uv@v5 - name: Create Django Major Issue run: uv run --frozen scripts/create_django_issue.py env: diff --git a/.github/workflows/ruff-version.yml b/.github/workflows/ruff-version.yml new file mode 100644 index 0000000000..a4f8b26173 --- /dev/null +++ b/.github/workflows/ruff-version.yml @@ -0,0 +1,37 @@ +name: ruff + +on: + pull_request: + paths: + - "{{cookiecutter.project_slug}}/requirements/local.txt" + +permissions: + contents: write + pull-requests: write + +jobs: + version: + runs-on: ubuntu-latest + env: + GH_PAT: ${{ secrets.GH_PAT }} + steps: + - name: Checkout with token + uses: actions/checkout@v4 + if: ${{ env.GH_PAT != '' }} + with: + token: ${{ env.GH_PAT }} + ref: ${{ github.head_ref }} + + - name: Checkout without token + uses: actions/checkout@v4 + if: ${{ env.GH_PAT == '' }} + with: + ref: ${{ github.head_ref }} + + - uses: astral-sh/setup-uv@v5 + + - run: uv run scripts/ruff_version.py + + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: Align Ruff versions diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 7ba5693805..18f55af091 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -16,9 +16,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: "true" + uses: astral-sh/setup-uv@v5 - name: Set git details run: | git config --global user.name "github-actions" diff --git a/.github/workflows/update-contributors.yml b/.github/workflows/update-contributors.yml index 1073fa4bec..d5c426e0fd 100644 --- a/.github/workflows/update-contributors.yml +++ b/.github/workflows/update-contributors.yml @@ -19,9 +19,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - enable-cache: "true" + uses: astral-sh/setup-uv@v5 - name: Update list run: uv run --frozen scripts/update_contributors.py env: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ca6730558c..87c828ba19 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,6 @@ exclude: "{{cookiecutter.project_slug}}|.github/contributors.json|CHANGELOG.md|CONTRIBUTORS.md" default_stages: [pre-commit] +minimum_pre_commit_version: "3.2.0" default_language_version: python: python3.12 @@ -26,7 +27,7 @@ repos: args: ["--tab-width", "2"] - repo: https://github.com/asottile/pyupgrade - rev: v3.19.0 + rev: v3.19.1 hooks: - id: pyupgrade args: [--py312-plus] @@ -52,6 +53,14 @@ repos: hooks: - id: pyproject-fmt + - repo: local + hooks: + - id: node-version-checker + name: node-version-checker + entry: python scripts/node_version.py + language: python + files: . + ci: autoupdate_schedule: weekly skip: [] diff --git a/CHANGELOG.md b/CHANGELOG.md index a71b71ef11..ad8ec678fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,385 @@ All enhancements and patches to Cookiecutter Django will be documented in this f +## 2025.01.16 + + +### Updated + +- Update ruff to 0.9.2 ([#5646](https://github.com/cookiecutter/cookiecutter-django/pull/5646)) + +- Bump amazon/aws-cli from 2.22.1 to 2.23.0 ([#5645](https://github.com/cookiecutter/cookiecutter-django/pull/5645)) + +## 2025.01.15 + + +### Fixed + +- Fix setting for to `CELERY_WORKER_HIJACK_ROOT_LOGGER` ([#5643](https://github.com/cookiecutter/cookiecutter-django/pull/5643)) + +### Updated + +- Update psycopg to 3.2.4 ([#5644](https://github.com/cookiecutter/cookiecutter-django/pull/5644)) + +- Update django-stubs to 5.1.2 ([#5639](https://github.com/cookiecutter/cookiecutter-django/pull/5639)) + +- Bump traefik from 3.3.1 to 3.3.2 ([#5642](https://github.com/cookiecutter/cookiecutter-django/pull/5642)) + +## 2025.01.14 + + +### Updated + +- Update django to 5.0.11 ([#5640](https://github.com/cookiecutter/cookiecutter-django/pull/5640)) + +- Update sentry-sdk to 2.20.0 ([#5638](https://github.com/cookiecutter/cookiecutter-django/pull/5638)) + +- Update django-debug-toolbar to 5.0.1 ([#5636](https://github.com/cookiecutter/cookiecutter-django/pull/5636)) + +## 2025.01.13 + + +### Updated + +- Update django-environ to 0.12.0 ([#5635](https://github.com/cookiecutter/cookiecutter-django/pull/5635)) + +- Bump traefik from 3.3.0 to 3.3.1 ([#5634](https://github.com/cookiecutter/cookiecutter-django/pull/5634)) + +## 2025.01.11 + + +### Updated + +- Update ruff to 0.9.1 ([#5633](https://github.com/cookiecutter/cookiecutter-django/pull/5633)) + +## 2025.01.10 + + +### Updated + +- Update watchfiles to 1.0.4 ([#5631](https://github.com/cookiecutter/cookiecutter-django/pull/5631)) + +## 2025.01.09 + + +### Changed + +- Drop support for Python 2 in template generation hooks ([#5614](https://github.com/cookiecutter/cookiecutter-django/pull/5614)) + +### Updated + +- Bump node from 22.12 to 22.13 ([#5627](https://github.com/cookiecutter/cookiecutter-django/pull/5627)) + +## 2025.01.07 + + +### Fixed + +- Set `minimum_pre_commit_version` in pre-commit config ([#5626](https://github.com/cookiecutter/cookiecutter-django/pull/5626)) + +### Updated + +- Bump traefik from 3.2.3 to 3.3.0 ([#5625](https://github.com/cookiecutter/cookiecutter-django/pull/5625)) + +## 2025.01.06 + + +### Changed + +- Add justfile for use with docker ([#5621](https://github.com/cookiecutter/cookiecutter-django/pull/5621)) + +## 2025.01.04 + + +### Updated + +- Update ruff to 0.8.6 ([#5622](https://github.com/cookiecutter/cookiecutter-django/pull/5622)) + +## 2025.01.02 + + +### Fixed + +- Fix logging configuration for Celery tasks ([#5563](https://github.com/cookiecutter/cookiecutter-django/pull/5563)) + +### Updated + +- Update ruff to 0.8.5 ([#5619](https://github.com/cookiecutter/cookiecutter-django/pull/5619)) + +- Update pillow to 11.1.0 ([#5617](https://github.com/cookiecutter/cookiecutter-django/pull/5617)) + +## 2024.12.27 + + +### Updated + +- Update coverage to 7.6.10 ([#5608](https://github.com/cookiecutter/cookiecutter-django/pull/5608)) + +- Update uvicorn-worker to 0.3.0 ([#5607](https://github.com/cookiecutter/cookiecutter-django/pull/5607)) + +## 2024.12.26 + + +### Updated + +- Update collectfasta to 3.2.1 ([#5606](https://github.com/cookiecutter/cookiecutter-django/pull/5606)) + +- Update django-allauth to 65.3.1 ([#5605](https://github.com/cookiecutter/cookiecutter-django/pull/5605)) + +## 2024.12.24 + + +### Updated + +- Update djlint to 1.36.4 ([#5603](https://github.com/cookiecutter/cookiecutter-django/pull/5603)) + +- Update uvicorn to 0.34.0 ([#5592](https://github.com/cookiecutter/cookiecutter-django/pull/5592)) + +## 2024.12.23 + + +### Updated + +- Bump webpack-cli from 5.1.4 to 6.0.1 ([#5601](https://github.com/cookiecutter/cookiecutter-django/pull/5601)) + +## 2024.12.20 + + +### Updated + +- Update ruff to 0.8.4 ([#5595](https://github.com/cookiecutter/cookiecutter-django/pull/5595)) + +## 2024.12.17 + + +### Updated + +- Update djangorestframework-stubs to 3.15.2 ([#5591](https://github.com/cookiecutter/cookiecutter-django/pull/5591)) + +- Bump traefik from 3.2.2 to 3.2.3 ([#5594](https://github.com/cookiecutter/cookiecutter-django/pull/5594)) + +## 2024.12.12 + + +### Updated + +- Update ruff to 0.8.3 ([#5587](https://github.com/cookiecutter/cookiecutter-django/pull/5587)) + +## 2024.12.11 + + +### Updated + +- Bump traefik from 3.2.1 to 3.2.2 ([#5586](https://github.com/cookiecutter/cookiecutter-django/pull/5586)) + +## 2024.12.10 + + +### Updated + +- Update watchfiles to 1.0.3 ([#5585](https://github.com/cookiecutter/cookiecutter-django/pull/5585)) + +- Bump node from 22.11 to 22.12 ([#5583](https://github.com/cookiecutter/cookiecutter-django/pull/5583)) + +## 2024.12.08 + + +### Fixed + +- Pin node to version 22.11 ([#5582](https://github.com/cookiecutter/cookiecutter-django/pull/5582)) + +### Updated + +- Update ruff to 0.8.2 ([#5576](https://github.com/cookiecutter/cookiecutter-django/pull/5576)) + +- Update coverage to 7.6.9 ([#5581](https://github.com/cookiecutter/cookiecutter-django/pull/5581)) + +- Update sentry-sdk to 2.19.2 ([#5579](https://github.com/cookiecutter/cookiecutter-django/pull/5579)) + +- Bump python from 3.12.7 to 3.12.8 in production Docker image ([#5575](https://github.com/cookiecutter/cookiecutter-django/pull/5575)) + +- Bump python from 3.12.7 to 3.12.8 in local Docker image ([#5574](https://github.com/cookiecutter/cookiecutter-django/pull/5574)) + +- Bump python from 3.12.7 to 3.12.8 in docs Docker image ([#5573](https://github.com/cookiecutter/cookiecutter-django/pull/5573)) + +- Update hiredis to 3.1.0 ([#5571](https://github.com/cookiecutter/cookiecutter-django/pull/5571)) + +- Update redis to 5.2.1 ([#5580](https://github.com/cookiecutter/cookiecutter-django/pull/5580)) + +- Update django to 5.0.10 ([#5572](https://github.com/cookiecutter/cookiecutter-django/pull/5572)) + +- Update drf-spectacular to 0.28.0 ([#5564](https://github.com/cookiecutter/cookiecutter-django/pull/5564)) + +## 2024.12.03 + + +### Updated + +- Update django-upgrade to 1.22.2 ([#5567](https://github.com/cookiecutter/cookiecutter-django/pull/5567)) + +## 2024.12.02 + + +### Updated + +- Update pytest to 8.3.4 ([#5566](https://github.com/cookiecutter/cookiecutter-django/pull/5566)) + +## 2024.12.01 + + +### Updated + +- Update django-allauth to 65.3.0 ([#5565](https://github.com/cookiecutter/cookiecutter-django/pull/5565)) + +## 2024.11.29 + + +### Updated + +- Update ruff to 0.8.1 ([#5557](https://github.com/cookiecutter/cookiecutter-django/pull/5557)) + +- Update djlint to 1.36.3 ([#5558](https://github.com/cookiecutter/cookiecutter-django/pull/5558)) + +## 2024.11.28 + + +### Updated + +- Update djlint to 1.36.2 ([#5555](https://github.com/cookiecutter/cookiecutter-django/pull/5555)) + +## 2024.11.27 + + +### Fixed + +- Pin dart-sass to 1.77.6 to avoid deprecation warnings ([#5552](https://github.com/cookiecutter/cookiecutter-django/pull/5552)) + +### Updated + +- Bump gulp-imagemin from 7.1.0 to 9.1.0 ([#5052](https://github.com/cookiecutter/cookiecutter-django/pull/5052)) + +- Bump gulp from 4.0.2 to 5.0.0 ([#4949](https://github.com/cookiecutter/cookiecutter-django/pull/4949)) + +## 2024.11.26 + + +### Updated + +- Update coverage to 7.6.8 ([#5547](https://github.com/cookiecutter/cookiecutter-django/pull/5547)) + +- Update watchfiles to 1.0.0 ([#5548](https://github.com/cookiecutter/cookiecutter-django/pull/5548)) + +## 2024.11.22 + + +### Updated + +- Update ruff to 0.8.0 ([#5545](https://github.com/cookiecutter/cookiecutter-django/pull/5545)) + +## 2024.11.21 + + +### Changed + +- Add support for secure Redis (TLS support) ([#5526](https://github.com/cookiecutter/cookiecutter-django/pull/5526)) + +### Updated + +- Update sentry-sdk to 2.19.0 ([#5543](https://github.com/cookiecutter/cookiecutter-django/pull/5543)) + +- Update uvicorn to 0.32.1 ([#5539](https://github.com/cookiecutter/cookiecutter-django/pull/5539)) + +- Bump traefik from 3.2.0 to 3.2.1 ([#5541](https://github.com/cookiecutter/cookiecutter-django/pull/5541)) + +## 2024.11.20 + + +### Fixed + +- Fix typos in translation instructions in README ([#5538](https://github.com/cookiecutter/cookiecutter-django/pull/5538)) + +### Updated + +- Bump amazon/aws-cli from 2.21.0 to 2.22.1 ([#5537](https://github.com/cookiecutter/cookiecutter-django/pull/5537)) + +## 2024.11.16 + + +### Updated + +- Update ruff to 0.7.4 ([#5531](https://github.com/cookiecutter/cookiecutter-django/pull/5531)) + +## 2024.11.15 + + +### Updated + +- Update coverage to 7.6.5 ([#5529](https://github.com/cookiecutter/cookiecutter-django/pull/5529)) + +## 2024.11.14 + + +### Updated + +- Bump amazon/aws-cli from 2.20.0 to 2.21.0 ([#5528](https://github.com/cookiecutter/cookiecutter-django/pull/5528)) + +## 2024.11.13 + + +### Updated + +- Update werkzeug to 3.1.3 ([#5524](https://github.com/cookiecutter/cookiecutter-django/pull/5524)) + +- Update ruff to 0.7.3 ([#5521](https://github.com/cookiecutter/cookiecutter-django/pull/5521)) + +- Bump amazon/aws-cli from 2.19.0 to 2.20.0 ([#5527](https://github.com/cookiecutter/cookiecutter-django/pull/5527)) + +- Update django-allauth to 65.2.0 ([#5523](https://github.com/cookiecutter/cookiecutter-django/pull/5523)) + +## 2024.11.08 + + +### Updated + +- Update ruff pre-commit hook to 0.7.3 ([#5522](https://github.com/cookiecutter/cookiecutter-django/pull/5522)) + +## 2024.11.07 + + +### Updated + +- Update djlint to 1.36.1 ([#5519](https://github.com/cookiecutter/cookiecutter-django/pull/5519)) + +## 2024.11.05 + + +### Updated + +- Update djlint to 1.36.0 ([#5517](https://github.com/cookiecutter/cookiecutter-django/pull/5517)) + +## 2024.11.04 + + +### Updated + +- Update sentry-sdk to 2.18.0 ([#5515](https://github.com/cookiecutter/cookiecutter-django/pull/5515)) + +## 2024.11.02 + + +### Updated + +- Update ruff to 0.7.2 ([#5510](https://github.com/cookiecutter/cookiecutter-django/pull/5510)) + +## 2024.11.01 + + +### Updated + +- Update djlint to 1.35.4 ([#5508](https://github.com/cookiecutter/cookiecutter-django/pull/5508)) + +- Bump amazon/aws-cli from 2.18.1 to 2.19.0 ([#5507](https://github.com/cookiecutter/cookiecutter-django/pull/5507)) + ## 2024.10.30 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 06c9c2db9f..74bd7acb23 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -733,6 +733,13 @@ Listed in alphabetical order. + + Denis Darii + + DNX + + + Denis Orehovsky @@ -992,6 +999,13 @@ Listed in alphabetical order. + + Hana Belay + + earthcomfy + + + Hana Quadara @@ -1881,6 +1895,13 @@ Listed in alphabetical order. + + Pulse-Mind + + pulse-mind + + + quroom @@ -1888,6 +1909,13 @@ Listed in alphabetical order. + + qwerrrqw + + qwerrrqw + + + Raony GuimarĂ£es CorrĂªa diff --git a/README.md b/README.md index 3b42a5e1bf..a46f214b42 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Powered by [Cookiecutter](https://github.com/cookiecutter/cookiecutter), Cookiec production-ready Django projects quickly. - Documentation: -- See [Troubleshooting](https://cookiecutter-django.readthedocs.io/en/latest/troubleshooting.html) for common errors and obstacles +- See [Troubleshooting](https://cookiecutter-django.readthedocs.io/en/latest/5-help/troubleshooting.html) for common errors and obstacles - If you have problems with Cookiecutter Django, please open [issues](https://github.com/cookiecutter/cookiecutter-django/issues/new) don't send emails to the maintainers. @@ -94,7 +94,7 @@ You'll be prompted for some values. Provide them, then a Django project will be **Warning**: After this point, change 'Daniel Greenfeld', 'pydanny', etc to your own information. -Answer the prompts with your own desired [options](http://cookiecutter-django.readthedocs.io/en/latest/project-generation-options.html). For example: +Answer the prompts with your own desired [options](http://cookiecutter-django.readthedocs.io/en/latest/1-getting-started/project-generation-options.html). For example: Cloning into 'cookiecutter-django'... remote: Counting objects: 550, done. diff --git a/docs/2-local-development/developing-locally-docker.rst b/docs/2-local-development/developing-locally-docker.rst index 05e188e527..07969e5b6c 100644 --- a/docs/2-local-development/developing-locally-docker.rst +++ b/docs/2-local-development/developing-locally-docker.rst @@ -242,6 +242,41 @@ The stack comes with a dedicated node service to build the static assets, watch .. _Sass: https://sass-lang.com/ .. _live reloading: https://browsersync.io + +Using Just for Docker Commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We have included a ``justfile`` to simplify the use of frequent Docker commands for local development. + +.. warning:: + Currently, "Just" does not reliably handle signals or forward them to its subprocesses. As a result, + pressing CTRL+C (or sending other signals like SIGTERM, SIGINT, or SIGHUP) may only interrupt + "Just" itself rather than its subprocesses. + For more information, see `this GitHub issue `_. + +First, install Just using one of the methods described in the `official documentation `_. + +Here are the available commands: + +- ``just build`` + Builds the Python image using the local Docker Compose file. + +- ``just up`` + Starts the containers in detached mode and removes orphaned containers. + +- ``just down`` + Stops the running containers. + +- ``just prune`` + Stops and removes containers along with their volumes. You can optionally pass an argument with the service name to prune a single container. + +- ``just logs`` + Shows container logs. You can optionally pass an argument with the service name to view logs for a specific service. + +- ``just manage `` + Runs Django management commands within the container. Replace ```` with any valid Django management command, such as ``migrate``, ``createsuperuser``, or ``shell``. + + (Optionally) Developing locally with HTTPS ------------------------------------------ diff --git a/docs/3-deployment/deployment-on-heroku.rst b/docs/3-deployment/deployment-on-heroku.rst index 75bf769365..292946ba37 100644 --- a/docs/3-deployment/deployment-on-heroku.rst +++ b/docs/3-deployment/deployment-on-heroku.rst @@ -14,6 +14,7 @@ Run these commands to deploy the project to Heroku: # Note: this is not a free plan heroku addons:create heroku-postgresql:essential-0 + # On Windows use double quotes for the time zone, e.g. # heroku pg:backups schedule --at "02:00 America/Los_Angeles" DATABASE_URL heroku pg:backups schedule --at '02:00 America/Los_Angeles' DATABASE_URL diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 1e2796eadf..63f6935313 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -1,16 +1,3 @@ -""" -NOTE: - the below code is to be maintained Python 2.x-compatible - as the whole Cookiecutter Django project initialization - can potentially be run in Python 2.x environment - (at least so we presume in `pre_gen_project.py`). - -TODO: restrict Cookiecutter Django project initialization to - Python 3.x environments only -""" - -from __future__ import print_function - import json import os import random @@ -82,6 +69,7 @@ def remove_docker_files(): "docker-compose.local.yml", "docker-compose.production.yml", ".dockerignore", + "justfile", ] for file_name in file_names: os.remove(file_name) @@ -114,7 +102,7 @@ def remove_sass_files(): def remove_gulp_files(): - file_names = ["gulpfile.js"] + file_names = ["gulpfile.mjs"] for file_name in file_names: os.remove(file_name) @@ -179,7 +167,7 @@ def handle_js_runner(choice, use_docker, use_async): remove_keys=["babel"], scripts={ "dev": "gulp", - "build": "gulp generate-assets", + "build": "gulp build", }, ) remove_webpack_files() diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 39559315a2..dd4c272436 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -1,15 +1,3 @@ -""" -NOTE: - the below code is to be maintained Python 2.x-compatible - as the whole Cookiecutter Django project initialization - can potentially be run in Python 2.x environment. - -TODO: restrict Cookiecutter Django project initialization - to Python 3.x environments only -""" - -from __future__ import print_function - import sys TERMINATOR = "\x1b[0m" @@ -28,17 +16,11 @@ project_slug = "{{ cookiecutter.project_slug }}" if hasattr(project_slug, "isidentifier"): - assert ( - project_slug.isidentifier() - ), "'{}' project slug is not a valid Python identifier.".format(project_slug) + assert project_slug.isidentifier(), "'{}' project slug is not a valid Python identifier.".format(project_slug) -assert ( - project_slug == project_slug.lower() -), "'{}' project slug should be all lowercase".format(project_slug) +assert project_slug == project_slug.lower(), "'{}' project slug should be all lowercase".format(project_slug) -assert ( - "\\" not in "{{ cookiecutter.author_name }}" -), "Don't include backslashes in author name." +assert "\\" not in "{{ cookiecutter.author_name }}", "Don't include backslashes in author name." if "{{ cookiecutter.use_docker }}".lower() == "n": python_major_version = sys.version_info[0] @@ -60,64 +42,42 @@ print( HINT + "Please respond with {} or {}: ".format( - ", ".join( - ["'{}'".format(o) for o in yes_options if not o == ""] - ), - ", ".join( - ["'{}'".format(o) for o in no_options if not o == ""] - ), + ", ".join(["'{}'".format(o) for o in yes_options if not o == ""]), + ", ".join(["'{}'".format(o) for o in no_options if not o == ""]), ) + TERMINATOR ) -if ( - "{{ cookiecutter.use_whitenoise }}".lower() == "n" - and "{{ cookiecutter.cloud_provider }}" == "None" -): - print( - "You should either use Whitenoise or select a " - "Cloud Provider to serve static files" - ) +if "{{ cookiecutter.use_whitenoise }}".lower() == "n" and "{{ cookiecutter.cloud_provider }}" == "None": + print("You should either use Whitenoise or select a " "Cloud Provider to serve static files") sys.exit(1) -if ( - "{{ cookiecutter.mail_service }}" == "Amazon SES" - and "{{ cookiecutter.cloud_provider }}" != "AWS" -): - print( - "You should either use AWS or select a different " - "Mail Service for sending emails." - ) +if "{{ cookiecutter.mail_service }}" == "Amazon SES" and "{{ cookiecutter.cloud_provider }}" != "AWS": + print("You should either use AWS or select a different " "Mail Service for sending emails.") sys.exit(1) # ----------------------------------------------------------------------------- # Forked additions - keeps diffs minimal # ----------------------------------------------------------------------------- -if ( - "{{ cookiecutter.use_docker }}".lower() == "n" - and "{{ cookiecutter.use_mosquitto }}".lower() == "y" -): +if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_mosquitto }}".lower() == "y": print("You cannot use Mosquitto without Docker") sys.exit(1) -if ( - "{{ cookiecutter.use_docker }}".lower() == "n" - and "{{ cookiecutter.use_prometheus }}".lower() == "y" -): +if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_prometheus }}".lower() == "y": print("You cannot use Prometheus without Docker") sys.exit(1) -if ( - "{{ cookiecutter.use_docker }}".lower() == "n" - and "{{ cookiecutter.use_grafana }}".lower() == "y" -): +if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_grafana }}".lower() == "y": print("You cannot use Grafana without Docker") sys.exit(1) -if ( - "{{ cookiecutter.use_docker }}".lower() == "n" - and "{{ cookiecutter.use_node_exporter }}".lower() == "y" -): +if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_node_exporter }}".lower() == "y": print("You cannot use Node Exporter without Docker") +if "{{ cookiecutter.use_whitenoise }}".lower() == "n" and "{{ cookiecutter.cloud_provider }}" == "None": + print("You should either use Whitenoise or select a Cloud Provider to serve static files") + sys.exit(1) + +if "{{ cookiecutter.mail_service }}" == "Amazon SES" and "{{ cookiecutter.cloud_provider }}" != "AWS": + print("You should either use AWS or select a different Mail Service for sending emails.") sys.exit(1) diff --git a/pyproject.toml b/pyproject.toml index 1c2ef36aaf..9f40258f68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cookiecutter-django" -version = "2024.10.30" +version = "2025.01.16" description = "A Cookiecutter template for creating production-ready Django projects quickly." readme = "README.md" keywords = [ @@ -32,22 +32,22 @@ classifiers = [ dependencies = [ "binaryornot==0.4.4", "cookiecutter==2.6", - "django-upgrade==1.21", - "djlint==1.35.2", + "django-upgrade==1.22.2", + "djlint==1.36.4", "gitpython==3.1.43", - "jinja2==3.1.4", + "jinja2==3.1.5", "pre-commit==3.8", - "pygithub==2.4", - "pytest==8.3.3", + "pygithub==2.5", + "pytest==8.3.4", "pytest-cookies==0.7", "pytest-instafail==0.5", "pytest-xdist==3.6.1", "pyyaml==6.0.2", "requests==2.32.3", - "ruff==0.7", - "sh==2.0.7; sys_platform!='win23'", - "tox==4.21.2", - "tox-uv>=1.11.2", + "ruff==0.9.2", + "sh==2.1; sys_platform!='win23'", + "tox==4.23.2", + "tox-uv>=1.17", ] urls = { Repository = "https://github.com/cookiecutter/cookiecutter-django" } @@ -76,6 +76,9 @@ known_first_party = [ "hooks", ] +[tool.pyproject-fmt] +keep_full_version = true + # ==== pytest ==== [tool.pytest.ini_options] diff --git a/scripts/node_version.py b/scripts/node_version.py new file mode 100644 index 0000000000..6264f8ee69 --- /dev/null +++ b/scripts/node_version.py @@ -0,0 +1,55 @@ +import json +from pathlib import Path + +ROOT = Path(__file__).parent.parent +TEMPLATED_ROOT = ROOT / "{{cookiecutter.project_slug}}" +DOCKERFILE = TEMPLATED_ROOT / "compose" / "local" / "node" / "Dockerfile" +PACKAGE_JSON = TEMPLATED_ROOT / "package.json" +CI_YML = ROOT / ".github" / "workflows" / "ci.yml" + + +def main(): + new_version = get_version_from_dockerfile() + old_version = get_version_from_package_json() + if old_version != new_version: + update_package_json_version(old_version, new_version) + update_ci_node_version(old_version, new_version) + + +def get_version_from_dockerfile(): + # Extract version out of base image name: + # FROM docker.io/node:22.13-bookworm-slim + # -> 22.13 + with DOCKERFILE.open("r") as f: + for line in f: + if "FROM docker.io/node:" in line: + _, _, docker_tag = line.partition(":") + version_str, _, _ = docker_tag.partition("-") + return version_str + + +def get_version_from_package_json(): + package_json = json.loads(PACKAGE_JSON.read_text()) + return package_json["engines"]["node"] + + +def update_package_json_version(old_version, new_version): + package_json_text = PACKAGE_JSON.read_text() + package_json_text = package_json_text.replace( + f'"node": "{old_version}"', + f'"node": "{new_version}"', + ) + PACKAGE_JSON.write_text(package_json_text) + + +def update_ci_node_version(old_version, new_version): + yml_content = CI_YML.read_text() + yml_content = yml_content.replace( + f'node-version: "{old_version}"', + f'node-version: "{new_version}"', + ) + CI_YML.write_text(yml_content) + + +if __name__ == "__main__": + main() diff --git a/scripts/ruff_version.py b/scripts/ruff_version.py new file mode 100644 index 0000000000..acc6beb14e --- /dev/null +++ b/scripts/ruff_version.py @@ -0,0 +1,53 @@ +import subprocess +import tomllib +from pathlib import Path + +ROOT = Path(__file__).parent.parent +TEMPLATED_ROOT = ROOT / "{{cookiecutter.project_slug}}" +REQUIREMENTS_LOCAL_TXT = TEMPLATED_ROOT / "requirements" / "local.txt" +PRE_COMMIT_CONFIG = TEMPLATED_ROOT / ".pre-commit-config.yaml" +PYPROJECT_TOML = ROOT / "pyproject.toml" + + +def main(): + new_version = get_requirements_txt_version() + old_version = get_pyproject_toml_version() + if old_version == new_version: + return + + update_ruff_version(old_version, new_version) + subprocess.run(["uv", "lock", "--no-upgrade"], cwd=ROOT) + + +def get_requirements_txt_version(): + content = REQUIREMENTS_LOCAL_TXT.read_text() + for line in content.split("\n"): + if line.startswith("ruff"): + return line.split(" ")[0].split("==")[1] + return None + + +def get_pyproject_toml_version(): + data = tomllib.loads(PYPROJECT_TOML.read_text()) + for dependency in data["project"]["dependencies"]: + if dependency.startswith("ruff=="): + return dependency.split("==")[1] + + +def update_ruff_version(old_version, new_version): + # Update pyproject.toml + new_content = PYPROJECT_TOML.read_text().replace( + f"ruff=={old_version}", + f"ruff=={new_version}", + ) + PYPROJECT_TOML.write_text(new_content) + # Update pre-commit config + new_content = PRE_COMMIT_CONFIG.read_text().replace( + f"repo: https://github.com/astral-sh/ruff-pre-commit\n rev: v{old_version}", + f"repo: https://github.com/astral-sh/ruff-pre-commit\n rev: v{new_version}", + ) + PRE_COMMIT_CONFIG.write_text(new_content) + + +if __name__ == "__main__": + main() diff --git a/scripts/update_changelog.py b/scripts/update_changelog.py index 9ef942c495..1bedebf5a4 100644 --- a/scripts/update_changelog.py +++ b/scripts/update_changelog.py @@ -53,10 +53,11 @@ def main() -> None: print(f"Updated version in {setup_py_path}") # Run uv lock - subprocess.run(["uv", "lock"], cwd=ROOT) + uv_lock_path = ROOT / "uv.lock" + subprocess.run(["uv", "lock", "--no-upgrade"], cwd=ROOT) # Commit changes, create tag and push - update_git_repo([changelog_path, setup_py_path], release) + update_git_repo([changelog_path, setup_py_path, uv_lock_path], release) # Create GitHub release github_release = repo.create_git_release( diff --git a/tests/test_docker.sh b/tests/test_docker.sh index 326e583286..171e0c8097 100755 --- a/tests/test_docker.sh +++ b/tests/test_docker.sh @@ -18,19 +18,19 @@ cd my_awesome_project docker compose -f docker-compose.local.yml build # run the project's type checks -docker compose -f docker-compose.local.yml run django mypy my_awesome_project +docker compose -f docker-compose.local.yml run --rm django mypy my_awesome_project # run the project's tests -docker compose -f docker-compose.local.yml run django pytest +docker compose -f docker-compose.local.yml run --rm django pytest # return non-zero status code if there are migrations that have not been created -docker compose -f docker-compose.local.yml run django python manage.py makemigrations --check || { echo "ERROR: there were changes in the models, but migration listed above have not been created and are not saved in version control"; exit 1; } +docker compose -f docker-compose.local.yml run --rm django python manage.py makemigrations --check || { echo "ERROR: there were changes in the models, but migration listed above have not been created and are not saved in version control"; exit 1; } # Test support for translations -docker compose -f docker-compose.local.yml run django python manage.py makemessages --all +docker compose -f docker-compose.local.yml run --rm django python manage.py makemessages --all # Make sure the check doesn't raise any warnings -docker compose -f docker-compose.local.yml run \ +docker compose -f docker-compose.local.yml run --rm \ -e DJANGO_SECRET_KEY="$(openssl rand -base64 64)" \ -e REDIS_URL=redis://redis:6379/0 \ -e DJANGO_AWS_ACCESS_KEY_ID=x \ @@ -42,10 +42,10 @@ docker compose -f docker-compose.local.yml run \ django python manage.py check --settings=config.settings.production --deploy --database default --fail-level WARNING # Generate the HTML for the documentation -docker compose -f docker-compose.docs.yml run docs make html +docker compose -f docker-compose.docs.yml run --rm docs make html # Run npm build script if package.json is present if [ -f "package.json" ] then - docker compose -f docker-compose.local.yml run node npm run build + docker compose -f docker-compose.local.yml run --rm node npm run build fi diff --git a/uv.lock b/uv.lock index c6944c41d5..f2321853dd 100644 --- a/uv.lock +++ b/uv.lock @@ -12,15 +12,16 @@ wheels = [ [[package]] name = "anyio" -version = "4.6.0" +version = "4.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, { name = "sniffio" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/78/49/f3f17ec11c4a91fe79275c426658e509b07547f874b14c1a526d86a83fc8/anyio-4.6.0.tar.gz", hash = "sha256:137b4559cbb034c477165047febb6ff83f390fc3b20bf181c1fc0a728cb8beeb", size = 170983 } +sdist = { url = "https://files.pythonhosted.org/packages/f6/40/318e58f669b1a9e00f5c4453910682e2d9dd594334539c7b7817dabb765f/anyio-4.7.0.tar.gz", hash = "sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48", size = 177076 } wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/ef/7a4f225581a0d7886ea28359179cb861d7fbcdefad29663fc1167b86f69f/anyio-4.6.0-py3-none-any.whl", hash = "sha256:c7d2e9d63e31599eeb636c8c5c03a7e108d73b345f064f1c19fdc87b79036a9a", size = 89631 }, + { url = "https://files.pythonhosted.org/packages/a0/7a/4daaf3b6c08ad7ceffea4634ec206faeff697526421c20f07628c7372156/anyio-4.7.0-py3-none-any.whl", hash = "sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352", size = 93052 }, ] [[package]] @@ -144,7 +145,7 @@ name = "click" version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ @@ -181,7 +182,7 @@ wheels = [ [[package]] name = "cookiecutter-django" -version = "2024.10.24" +version = "2025.1.15" source = { virtual = "." } dependencies = [ { name = "binaryornot" }, @@ -204,7 +205,7 @@ dependencies = [ { name = "tox-uv" }, ] -[package.dependency-groups] +[package.dev-dependencies] docs = [ { name = "myst-parser" }, { name = "sphinx" }, @@ -216,25 +217,25 @@ docs = [ requires-dist = [ { name = "binaryornot", specifier = "==0.4.4" }, { name = "cookiecutter", specifier = "==2.6" }, - { name = "django-upgrade", specifier = "==1.21" }, - { name = "djlint", specifier = "==1.35.2" }, + { name = "django-upgrade", specifier = "==1.22.2" }, + { name = "djlint", specifier = "==1.36.4" }, { name = "gitpython", specifier = "==3.1.43" }, - { name = "jinja2", specifier = "==3.1.4" }, + { name = "jinja2", specifier = "==3.1.5" }, { name = "pre-commit", specifier = "==3.8" }, - { name = "pygithub", specifier = "==2.4" }, - { name = "pytest", specifier = "==8.3.3" }, + { name = "pygithub", specifier = "==2.5" }, + { name = "pytest", specifier = "==8.3.4" }, { name = "pytest-cookies", specifier = "==0.7" }, { name = "pytest-instafail", specifier = "==0.5" }, { name = "pytest-xdist", specifier = "==3.6.1" }, { name = "pyyaml", specifier = "==6.0.2" }, { name = "requests", specifier = "==2.32.3" }, - { name = "ruff", specifier = "==0.7" }, - { name = "sh", marker = "sys_platform != 'win23'", specifier = "==2.0.7" }, - { name = "tox", specifier = "==4.21.2" }, - { name = "tox-uv", specifier = ">=1.11.2" }, + { name = "ruff", specifier = "==0.9.2" }, + { name = "sh", marker = "sys_platform != 'win23'", specifier = "==2.1" }, + { name = "tox", specifier = "==4.23.2" }, + { name = "tox-uv", specifier = ">=1.17" }, ] -[package.metadata.dependency-groups] +[package.metadata.requires-dev] docs = [ { name = "myst-parser", specifier = ">=4" }, { name = "sphinx", specifier = ">=8.0.2" }, @@ -305,26 +306,24 @@ wheels = [ [[package]] name = "django-upgrade" -version = "1.21.0" +version = "1.22.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tokenize-rt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2e/30/5215e526e054831cbbc454ce81fb5e825224019824a185e3c011cf199b90/django_upgrade-1.21.0.tar.gz", hash = "sha256:e65021029e7d18b407bd128a8ccb31e5e06685068b37b6b1eaf2f77aa3d3df98", size = 66708 } +sdist = { url = "https://files.pythonhosted.org/packages/f3/46/24e32ffdad682df8c273e2f434096246c89d265948a2fd214307f31eeeec/django_upgrade-1.22.2.tar.gz", hash = "sha256:8643abdde2961e3c60173ebee84f48371ffbec5181095a38cac080947af0d2ae", size = 67932 } wheels = [ - { url = "https://files.pythonhosted.org/packages/56/76/7a7eeb88657abf8a0f97fbab4f6600be2ec89577e3695c395b47e6860ec5/django_upgrade-1.21.0-py3-none-any.whl", hash = "sha256:a0a7b11d5108fb2d3038cea2382c1332c9be4ff5059a38357fbd28116ebf3803", size = 67796 }, + { url = "https://files.pythonhosted.org/packages/98/64/7b1432a7eca9e8e24b27ef89b9badca59add35a6dc785a63aa886b167c9d/django_upgrade-1.22.2-py3-none-any.whl", hash = "sha256:fb76b183b2e8186bb1157734083569a4b754dce2e812c2a723454bd248fb1373", size = 69114 }, ] [[package]] name = "djlint" -version = "1.35.2" +version = "1.36.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "colorama" }, { name = "cssbeautifier" }, - { name = "html-tag-names" }, - { name = "html-void-elements" }, { name = "jsbeautifier" }, { name = "json5" }, { name = "pathspec" }, @@ -332,9 +331,13 @@ dependencies = [ { name = "regex" }, { name = "tqdm" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a4/ee/ac8ee551ec04d5a214e62d008f40bf309574f103416482e03fb61fbad61c/djlint-1.35.2.tar.gz", hash = "sha256:318de9d4b9b0061a111f8f5164ecbacd8215f449dd4bd5a76d2a691c815ee103", size = 44684 } +sdist = { url = "https://files.pythonhosted.org/packages/74/89/ecf5be9f5c59a0c53bcaa29671742c5e269cc7d0e2622e3f65f41df251bf/djlint-1.36.4.tar.gz", hash = "sha256:17254f218b46fe5a714b224c85074c099bcb74e3b2e1f15c2ddc2cf415a408a1", size = 47849 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/31/297cad1a493f2910d366418acd0f33da908dfb8b16b8d6c6bafddac4fa7d/djlint-1.35.2-py3-none-any.whl", hash = "sha256:4ba995bad378f2afa77c8ea56ba1c14429d9ff26a18e8ae23bc71eedb9152243", size = 50641 }, + { url = "https://files.pythonhosted.org/packages/53/f5/9ae02b875604755d4d00cebf96b218b0faa3198edc630f56a139581aed87/djlint-1.36.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ff9faffd7d43ac20467493fa71d5355b5b330a00ade1c4d1e859022f4195223b", size = 354886 }, + { url = "https://files.pythonhosted.org/packages/97/51/284443ff2f2a278f61d4ae6ae55eaf820ad9f0fd386d781cdfe91f4de495/djlint-1.36.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:79489e262b5ac23a8dfb7ca37f1eea979674cfc2d2644f7061d95bea12c38f7e", size = 323237 }, + { url = "https://files.pythonhosted.org/packages/6d/5e/791f4c5571f3f168ad26fa3757af8f7a05c623fde1134a9c4de814ee33b7/djlint-1.36.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e58c5fa8c6477144a0be0a87273706a059e6dd0d6efae01146ae8c29cdfca675", size = 411719 }, + { url = "https://files.pythonhosted.org/packages/1f/11/894425add6f84deffcc6e373f2ce250f2f7b01aa58c7f230016ebe7a0085/djlint-1.36.4-cp312-cp312-win_amd64.whl", hash = "sha256:bb6903777bf3124f5efedcddf1f4716aef097a7ec4223fc0fa54b865829a6e08", size = 362076 }, + { url = "https://files.pythonhosted.org/packages/4b/67/f7aeea9be6fb3bd984487af8d0d80225a0b1e5f6f7126e3332d349fb13fe/djlint-1.36.4-py3-none-any.whl", hash = "sha256:e9699b8ac3057a6ed04fb90835b89bee954ed1959c01541ce4f8f729c938afdd", size = 52290 }, ] [[package]] @@ -403,24 +406,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, ] -[[package]] -name = "html-tag-names" -version = "0.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/41/7c/8c0dc3c5650036127fb4629d31cadf6cbdd57e21a77f9793fa8b2c8a3241/html-tag-names-0.1.2.tar.gz", hash = "sha256:04924aca48770f36b5a41c27e4d917062507be05118acb0ba869c97389084297", size = 15173 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/e4/242318dcaa06d8525ff72332fc15cea2cffb84c06cfc73c7da6c6b45801a/html_tag_names-0.1.2-py3-none-any.whl", hash = "sha256:eeb69ef21078486b615241f0393a72b41352c5219ee648e7c61f5632d26f0420", size = 15218 }, -] - -[[package]] -name = "html-void-elements" -version = "0.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/80/5c/5f17d77256bf78ca98647517fadee50575e75d812daa01352c31d89d5bf2/html-void-elements-0.1.0.tar.gz", hash = "sha256:931b88f84cd606fee0b582c28fcd00e41d7149421fb673e1e1abd2f0c4f231f0", size = 14766 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/0a/373f28a1cf37f8c9aa23c82cbcac7197ddea95c88b5a3eaa564cdb8de375/html_void_elements-0.1.0-py3-none-any.whl", hash = "sha256:784cf39db03cdeb017320d9301009f8f3480f9d7b254d0974272e80e0cb5e0d2", size = 14889 }, -] - [[package]] name = "identify" version = "2.6.0" @@ -459,14 +444,14 @@ wheels = [ [[package]] name = "jinja2" -version = "3.1.4" +version = "3.1.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 } +sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 }, + { url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 }, ] [[package]] @@ -628,7 +613,7 @@ wheels = [ [[package]] name = "pygithub" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "deprecated" }, @@ -638,9 +623,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/a0/1e8b8ca88df9857836f5bf8e3ee15dfb810d19814ef700b12f99ce11f691/pygithub-2.4.0.tar.gz", hash = "sha256:6601e22627e87bac192f1e2e39c6e6f69a43152cfb8f307cee575879320b3051", size = 3476673 } +sdist = { url = "https://files.pythonhosted.org/packages/16/ce/aa91d30040d9552c274e7ea8bd10a977600d508d579a4bb262b95eccf961/pygithub-2.5.0.tar.gz", hash = "sha256:e1613ac508a9be710920d26eb18b1905ebd9926aa49398e88151c1b526aad3cf", size = 3552804 } wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/f3/e185613c411757c0c18b904ea2db173f2872397eddf444a3fe8cdde47077/PyGithub-2.4.0-py3-none-any.whl", hash = "sha256:81935aa4bdc939fba98fee1cb47422c09157c56a27966476ff92775602b9ee24", size = 362599 }, + { url = "https://files.pythonhosted.org/packages/37/05/bfbdbbc5d8aafd8dae9b3b6877edca561fccd8528ef5edc4e7b6d23721b5/PyGithub-2.5.0-py3-none-any.whl", hash = "sha256:b0b635999a658ab8e08720bdd3318893ff20e2275f6446fcf35bf3f44f2c0fd2", size = 375935 }, ] [[package]] @@ -700,7 +685,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.3.3" +version = "8.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -708,9 +693,9 @@ dependencies = [ { name = "packaging" }, { name = "pluggy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/6c/62bbd536103af674e227c41a8f3dcd022d591f6eed5facb5a0f31ee33bbc/pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", size = 1442487 } +sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/77/7440a06a8ead44c7757a64362dd22df5760f9b12dc5f11b6188cd2fc27a0/pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2", size = 342341 }, + { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, ] [[package]] @@ -845,36 +830,36 @@ wheels = [ [[package]] name = "ruff" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2c/c7/f3367d1da5d568192968c5c9e7f3d51fb317b9ac04828493b23d8fce8ce6/ruff-0.7.0.tar.gz", hash = "sha256:47a86360cf62d9cd53ebfb0b5eb0e882193fc191c6d717e8bef4462bc3b9ea2b", size = 3146645 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/48/59/a0275a0913f3539498d116046dd679cd657fe3b7caf5afe1733319414932/ruff-0.7.0-py3-none-linux_armv6l.whl", hash = "sha256:0cdf20c2b6ff98e37df47b2b0bd3a34aaa155f59a11182c1303cce79be715628", size = 10434007 }, - { url = "https://files.pythonhosted.org/packages/cd/94/da0ba5f956d04c90dd899209904210600009dcda039ce840d83eb4298c7d/ruff-0.7.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:496494d350c7fdeb36ca4ef1c9f21d80d182423718782222c29b3e72b3512737", size = 10048066 }, - { url = "https://files.pythonhosted.org/packages/57/1d/e5cc149ecc46e4f203403a79ccd170fad52d316f98b87d0f63b1945567db/ruff-0.7.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:214b88498684e20b6b2b8852c01d50f0651f3cc6118dfa113b4def9f14faaf06", size = 9711389 }, - { url = "https://files.pythonhosted.org/packages/05/67/fb7ea2c869c539725a16c5bc294e9aa34f8b1b6fe702f1d173a5da517c2b/ruff-0.7.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630fce3fefe9844e91ea5bbf7ceadab4f9981f42b704fae011bb8efcaf5d84be", size = 10755174 }, - { url = "https://files.pythonhosted.org/packages/5f/f0/13703bc50536a0613ea3dce991116e5f0917a1f05528c6ab738b33c08d3f/ruff-0.7.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:211d877674e9373d4bb0f1c80f97a0201c61bcd1e9d045b6e9726adc42c156aa", size = 10196040 }, - { url = "https://files.pythonhosted.org/packages/99/c1/77b04ab20324ab03d333522ee55fb0f1c38e3ca0d326b4905f82ce6b6c70/ruff-0.7.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:194d6c46c98c73949a106425ed40a576f52291c12bc21399eb8f13a0f7073495", size = 11033684 }, - { url = "https://files.pythonhosted.org/packages/f2/97/f463334dc4efeea3551cd109163df15561c18a1c3ec13d51643740fd36ba/ruff-0.7.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:82c2579b82b9973a110fab281860403b397c08c403de92de19568f32f7178598", size = 11803700 }, - { url = "https://files.pythonhosted.org/packages/b4/f8/a31d40c4bb92933d376a53e7c5d0245d9b27841357e4820e96d38f54b480/ruff-0.7.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9af971fe85dcd5eaed8f585ddbc6bdbe8c217fb8fcf510ea6bca5bdfff56040e", size = 11347848 }, - { url = "https://files.pythonhosted.org/packages/83/62/0c133b35ddaf91c65c30a56718b80bdef36bfffc35684d29e3a4878e0ea3/ruff-0.7.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b641c7f16939b7d24b7bfc0be4102c56562a18281f84f635604e8a6989948914", size = 12480632 }, - { url = "https://files.pythonhosted.org/packages/46/96/464058dd1d980014fb5aa0a1254e78799efb3096fc7a4823cd66a1621276/ruff-0.7.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d71672336e46b34e0c90a790afeac8a31954fd42872c1f6adaea1dff76fd44f9", size = 10941919 }, - { url = "https://files.pythonhosted.org/packages/a0/f7/bda37ec77986a435dde44e1f59374aebf4282a5fa9cf17735315b847141f/ruff-0.7.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ab7d98c7eed355166f367597e513a6c82408df4181a937628dbec79abb2a1fe4", size = 10745519 }, - { url = "https://files.pythonhosted.org/packages/c2/33/5f77fc317027c057b61a848020a47442a1cbf12e592df0e41e21f4d0f3bd/ruff-0.7.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1eb54986f770f49edb14f71d33312d79e00e629a57387382200b1ef12d6a4ef9", size = 10284872 }, - { url = "https://files.pythonhosted.org/packages/ff/50/98aec292bc9537f640b8d031c55f3414bf15b6ed13b3e943fed75ac927b9/ruff-0.7.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dc452ba6f2bb9cf8726a84aa877061a2462afe9ae0ea1d411c53d226661c601d", size = 10600334 }, - { url = "https://files.pythonhosted.org/packages/f2/85/12607ae3201423a179b8cfadc7cb1e57d02cd0135e45bd0445acb4cef327/ruff-0.7.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4b406c2dce5be9bad59f2de26139a86017a517e6bcd2688da515481c05a2cb11", size = 11017333 }, - { url = "https://files.pythonhosted.org/packages/d4/7f/3b85a56879e705d5f46ec14daf8a439fca05c3081720fe3dc3209100922d/ruff-0.7.0-py3-none-win32.whl", hash = "sha256:f6c968509f767776f524a8430426539587d5ec5c662f6addb6aa25bc2e8195ec", size = 8570962 }, - { url = "https://files.pythonhosted.org/packages/39/9f/c5ee2b40d377354dabcc23cff47eb299de4b4d06d345068f8f8cc1eadac8/ruff-0.7.0-py3-none-win_amd64.whl", hash = "sha256:ff4aabfbaaba880e85d394603b9e75d32b0693152e16fa659a3064a85df7fce2", size = 9365544 }, - { url = "https://files.pythonhosted.org/packages/89/8b/ee1509f60148cecba644aa718f6633216784302458340311898aaf0b1bed/ruff-0.7.0-py3-none-win_arm64.whl", hash = "sha256:10842f69c245e78d6adec7e1db0a7d9ddc2fff0621d730e61657b64fa36f207e", size = 8695763 }, +version = "0.9.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/80/63/77ecca9d21177600f551d1c58ab0e5a0b260940ea7312195bd2a4798f8a8/ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0", size = 3553799 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/b9/0e168e4e7fb3af851f739e8f07889b91d1a33a30fca8c29fa3149d6b03ec/ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347", size = 11652408 }, + { url = "https://files.pythonhosted.org/packages/2c/22/08ede5db17cf701372a461d1cb8fdde037da1d4fa622b69ac21960e6237e/ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00", size = 11587553 }, + { url = "https://files.pythonhosted.org/packages/42/05/dedfc70f0bf010230229e33dec6e7b2235b2a1b8cbb2a991c710743e343f/ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4", size = 11020755 }, + { url = "https://files.pythonhosted.org/packages/df/9b/65d87ad9b2e3def67342830bd1af98803af731243da1255537ddb8f22209/ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d", size = 11826502 }, + { url = "https://files.pythonhosted.org/packages/93/02/f2239f56786479e1a89c3da9bc9391120057fc6f4a8266a5b091314e72ce/ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c", size = 11390562 }, + { url = "https://files.pythonhosted.org/packages/c9/37/d3a854dba9931f8cb1b2a19509bfe59e00875f48ade632e95aefcb7a0aee/ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f", size = 12548968 }, + { url = "https://files.pythonhosted.org/packages/fa/c3/c7b812bb256c7a1d5553433e95980934ffa85396d332401f6b391d3c4569/ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684", size = 13187155 }, + { url = "https://files.pythonhosted.org/packages/bd/5a/3c7f9696a7875522b66aa9bba9e326e4e5894b4366bd1dc32aa6791cb1ff/ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d", size = 12704674 }, + { url = "https://files.pythonhosted.org/packages/be/d6/d908762257a96ce5912187ae9ae86792e677ca4f3dc973b71e7508ff6282/ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df", size = 14529328 }, + { url = "https://files.pythonhosted.org/packages/2d/c2/049f1e6755d12d9cd8823242fa105968f34ee4c669d04cac8cea51a50407/ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247", size = 12385955 }, + { url = "https://files.pythonhosted.org/packages/91/5a/a9bdb50e39810bd9627074e42743b00e6dc4009d42ae9f9351bc3dbc28e7/ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e", size = 11810149 }, + { url = "https://files.pythonhosted.org/packages/e5/fd/57df1a0543182f79a1236e82a79c68ce210efb00e97c30657d5bdb12b478/ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe", size = 11479141 }, + { url = "https://files.pythonhosted.org/packages/dc/16/bc3fd1d38974f6775fc152a0554f8c210ff80f2764b43777163c3c45d61b/ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb", size = 12014073 }, + { url = "https://files.pythonhosted.org/packages/47/6b/e4ca048a8f2047eb652e1e8c755f384d1b7944f69ed69066a37acd4118b0/ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a", size = 12435758 }, + { url = "https://files.pythonhosted.org/packages/c2/40/4d3d6c979c67ba24cf183d29f706051a53c36d78358036a9cd21421582ab/ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145", size = 9796916 }, + { url = "https://files.pythonhosted.org/packages/c3/ef/7f548752bdb6867e6939489c87fe4da489ab36191525fadc5cede2a6e8e2/ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5", size = 10773080 }, + { url = "https://files.pythonhosted.org/packages/0e/4e/33df635528292bd2d18404e4daabcd74ca8a9853b2e1df85ed3d32d24362/ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6", size = 10001738 }, ] [[package]] name = "sh" -version = "2.0.7" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/14/7a/5148402146d360a6d15922814a3b065b52be3a5fe878a8834d3ce4e7d33f/sh-2.0.7.tar.gz", hash = "sha256:029d45198902bfb967391eccfd13a88d92f7cebd200411e93f99ebacc6afbb35", size = 345477 } +sdist = { url = "https://files.pythonhosted.org/packages/52/12/b7965006c5adc57ba5459385358bd27c4983cd490884a75be86eb1d3efeb/sh-2.1.0.tar.gz", hash = "sha256:7e27301c574bec8ca5bf6f211851357526455ee97cd27a7c4c6cc5e2375399cb", size = 345525 } wheels = [ - { url = "https://files.pythonhosted.org/packages/15/c2/79f9dea6fc544c0eb79ed5018a38860c52d597c4be66c2cf2029bea5b3fd/sh-2.0.7-py3-none-any.whl", hash = "sha256:2f2f79a65abd00696cf2e9ad26508cf8abb6dba5745f40255f1c0ded2876926d", size = 38103 }, + { url = "https://files.pythonhosted.org/packages/00/59/f6551f49c123751e921038c24215157bd50aef375ced16cac57229678c43/sh-2.1.0-py3-none-any.whl", hash = "sha256:bf5e44178dd96a542126c2774e9b7ab1d89bfe0e2ef84d92e6d0ed7358d63d01", size = 38080 }, ] [[package]] @@ -915,7 +900,7 @@ wheels = [ [[package]] name = "sphinx" -version = "8.0.2" +version = "8.1.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "alabaster" }, @@ -935,9 +920,9 @@ dependencies = [ { name = "sphinxcontrib-qthelp" }, { name = "sphinxcontrib-serializinghtml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/a7/3cc3d6dcad70aba2e32a3ae8de5a90026a0a2fdaaa0756925e3a120249b6/sphinx-8.0.2.tar.gz", hash = "sha256:0cce1ddcc4fd3532cf1dd283bc7d886758362c5c1de6598696579ce96d8ffa5b", size = 8189041 } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/61/2ad169c6ff1226b46e50da0e44671592dbc6d840a52034a0193a99b28579/sphinx-8.0.2-py3-none-any.whl", hash = "sha256:56173572ae6c1b9a38911786e206a110c9749116745873feae4f9ce88e59391d", size = 3498950 }, + { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125 }, ] [[package]] @@ -959,16 +944,16 @@ wheels = [ [[package]] name = "sphinx-rtd-theme" -version = "3.0.0" +version = "3.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils" }, { name = "sphinx" }, { name = "sphinxcontrib-jquery" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/21/f8/2667f9cab89827528596588dd9de6f937f52e5c6e87e6f28ecb866955551/sphinx_rtd_theme-3.0.0.tar.gz", hash = "sha256:905d67de03217fd3d76fbbdd992034ac8e77044ef8063a544dda1af74d409e08", size = 7620317 } +sdist = { url = "https://files.pythonhosted.org/packages/91/44/c97faec644d29a5ceddd3020ae2edffa69e7d00054a8c7a6021e82f20335/sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85", size = 7620463 } wheels = [ - { url = "https://files.pythonhosted.org/packages/21/11/81e5bfffdbd6dd3173d5ee29b4629a03ba80d38d4a250e7a8504af22d5c2/sphinx_rtd_theme-3.0.0-py2.py3-none-any.whl", hash = "sha256:1ffe1539957775bfa0a7331370de7dc145b6eac705de23365dc55c5d94bb08e7", size = 7655495 }, + { url = "https://files.pythonhosted.org/packages/85/77/46e3bac77b82b4df5bb5b61f2de98637724f246b4966cfc34bc5895d852a/sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13", size = 7655561 }, ] [[package]] @@ -1039,14 +1024,14 @@ wheels = [ [[package]] name = "starlette" -version = "0.39.2" +version = "0.45.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/02/0a/62fbd5697f6174041f9b4e2e377b6f383f9189b77dbb7d73d24624caca1d/starlette-0.39.2.tar.gz", hash = "sha256:caaa3b87ef8518ef913dac4f073dea44e85f73343ad2bdc17941931835b2a26a", size = 2573080 } +sdist = { url = "https://files.pythonhosted.org/packages/c1/be/b398217eb35b356d2d9bb84ec67071ea2842e02950fcf38b33df9d5b24ba/starlette-0.45.1.tar.gz", hash = "sha256:a8ae1fa3b1ab7ca83a4abd77871921a13fb5aeaf4874436fb96c29dfcd4ecfa3", size = 2573953 } wheels = [ - { url = "https://files.pythonhosted.org/packages/60/f0/04547f776c8845be46df4bdd1f11159c088bd39e916f35d7da1b9f6eb3ef/starlette-0.39.2-py3-none-any.whl", hash = "sha256:134dd6deb655a9775991d352312d53f1879775e5cc8a481f966e83416a2c3f71", size = 73219 }, + { url = "https://files.pythonhosted.org/packages/6b/2c/a50484b035ee0e13ebb7a42391e391befbfc1b6a9ad5503e83badd182ada/starlette-0.45.1-py3-none-any.whl", hash = "sha256:5656c0524f586e9148d9a3c1dd5257fb42a99892fb0dc6877dd76ef4d184aac3", size = 71488 }, ] [[package]] @@ -1069,7 +1054,7 @@ wheels = [ [[package]] name = "tox" -version = "4.21.2" +version = "4.23.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cachetools" }, @@ -1082,23 +1067,23 @@ dependencies = [ { name = "pyproject-api" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2a/db/ba5b1a4cf664f221a33c3cbb1adf40ccccbbd13f5eec6d9d7291c7a39e44/tox-4.21.2.tar.gz", hash = "sha256:49381ff102296753e378fa5ff30e42a35e695f149b4dbf8a2c49d15fdb5797b2", size = 188539 } +sdist = { url = "https://files.pythonhosted.org/packages/1f/86/32b10f91b4b975a37ac402b0f9fa016775088e0565c93602ba0b3c729ce8/tox-4.23.2.tar.gz", hash = "sha256:86075e00e555df6e82e74cfc333917f91ecb47ffbc868dcafbd2672e332f4a2c", size = 189998 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/20/168300f3f334e255b618322dce14b86a5c423aab05f28be14d1a2d6af14a/tox-4.21.2-py3-none-any.whl", hash = "sha256:13d996adcd792e7c82994b0e116d85efd84f0c6d185254d83d156f73f86b2038", size = 165698 }, + { url = "https://files.pythonhosted.org/packages/af/c0/124b73d01c120e917383bc6c53ebc34efdf7243faa9fca64d105c94cf2ab/tox-4.23.2-py3-none-any.whl", hash = "sha256:452bc32bb031f2282881a2118923176445bac783ab97c874b8770ab4c3b76c38", size = 166758 }, ] [[package]] name = "tox-uv" -version = "1.11.2" +version = "1.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, { name = "tox" }, { name = "uv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fa/cf/7062095ae8c5e6a25d7153b9b1c4a16e52df61859160b3db66a60f055d1e/tox_uv-1.11.2.tar.gz", hash = "sha256:a7aded5c3fb69f055b523357988c1055bb573e91bfd7ecfb9b5233ebcab5d10b", size = 13628 } +sdist = { url = "https://files.pythonhosted.org/packages/57/e3/04e7430a21290aaf91087123055249052f9bafaa48178f4ab58b8d73d839/tox_uv-1.17.0.tar.gz", hash = "sha256:07020acd90048b5c898b2c8f1e7c1c4cf944161745d7bfe5b9458ed67f4998b7", size = 17640 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/50/5b9f2d9d10bfdfb1f748bbcdb6eae5a5da6d2a7adbef9a4df34aceac6eca/tox_uv-1.11.2-py3-none-any.whl", hash = "sha256:7f8f1737b3277e1cddcb5b89fcc5931d04923562c940ae60f29e140908566df2", size = 11265 }, + { url = "https://files.pythonhosted.org/packages/fa/be/fc8209e150fec799fd01fa027f372cdf87d6cf0eeb083e43ee48037199e5/tox_uv-1.17.0-py3-none-any.whl", hash = "sha256:cdc95eca6fd98a7716b9da7c9cf901d4836d6956089d6cb3417f00c8d98b513c", size = 14010 }, ] [[package]] @@ -1106,7 +1091,7 @@ name = "tqdm" version = "4.66.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/58/83/6ba9844a41128c62e810fddddd72473201f3eacde02046066142a2d96cc5/tqdm-4.66.5.tar.gz", hash = "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad", size = 169504 } wheels = [ @@ -1142,40 +1127,39 @@ wheels = [ [[package]] name = "uv" -version = "0.4.6" +version = "0.5.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/02/5c/916bc1eacf2a5ca8cd33dc5d51cc9f64735ef6faccefd2f689d34b9eb23a/uv-0.4.6.tar.gz", hash = "sha256:5c142b0082844c9eca4a303e13cf1d286622f49af70e8f922b833cb3e667b2e3", size = 1859862 } +sdist = { url = "https://files.pythonhosted.org/packages/a4/09/dc3b7beb8abc663c962320eff9862e5c718383bd6e03e9490da5621f77c5/uv-0.5.13.tar.gz", hash = "sha256:58a66786f2e95c89539bafd819cf2959f56199457301eac8faa920c1872c4f36", size = 2555484 } wheels = [ - { url = "https://files.pythonhosted.org/packages/09/0b/eb3ca96aa881e5a88e704b5d7aec99610cc0d64702c984da24ae2a5682c2/uv-0.4.6-py3-none-linux_armv6l.whl", hash = "sha256:e0360bb3b094d106d1fa00b3a15c69ccd0d1593682c33affb1b94367a248a378", size = 11097185 }, - { url = "https://files.pythonhosted.org/packages/30/1c/3c27e0fe4ad1a5b9792a61e92283457beec7949863c1b3435ef79cfad179/uv-0.4.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:16ae9f0a9b3bb6db755d057c4ff55b0e82fbb09243a1dce02720268718c0a11c", size = 11558713 }, - { url = "https://files.pythonhosted.org/packages/5a/f8/93e8574c91ef7884154af6f80d213ee11f7710201c2fe0d73a9f9556bd2d/uv-0.4.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6e925f661aeaf392cc102d3c2f6f05b6994519bd7a36578f836a4bbf42ee813", size = 10668873 }, - { url = "https://files.pythonhosted.org/packages/0f/f3/1b2625aa119ee66fc7a6c3c1026c66707a5f99a0c86e5d49fd237f45f0b5/uv-0.4.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:86f78fb80989b524ce7da705fb5af613339a8eadbcf9e230bb16e8a7d383c2ce", size = 11006778 }, - { url = "https://files.pythonhosted.org/packages/30/01/cbe8bc23dd1e32b77b652e31757fcdb636c194bd13acf32e2438a72daf5a/uv-0.4.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a66442018e09467222824b685b2d401053dfdbc3b5f6fb1f863ca2eb2560076a", size = 10896611 }, - { url = "https://files.pythonhosted.org/packages/5f/11/46328fc827f4bf35b715a97f067a61563f5421e0e35ba6fd16b9de82771a/uv-0.4.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4db5c2b770bb0e95a4d32dc19943109310c86103fe8b8ecf0d18dfe1a4f2a212", size = 11563597 }, - { url = "https://files.pythonhosted.org/packages/3e/b1/8774d2fab7cbec44e68aafa58745ce9ec2af26a17e1d6ad86284fcd79acf/uv-0.4.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9bf486c6331197a301bff253945b233d852ed2fdc322e93c78d382092813161d", size = 12341920 }, - { url = "https://files.pythonhosted.org/packages/81/cc/f53877269f75d4bba8e4bad131b6aa2d39d6545afff2c703be2c9608ad50/uv-0.4.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2bd9879eb8ee9de0fa532136ddfe76c1b425520fa6de52f5d023567e226a08b5", size = 12142981 }, - { url = "https://files.pythonhosted.org/packages/13/b8/373d86645849320eb61e213e657084f7cf6be2d6f2b13e413cb555876659/uv-0.4.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831be24db75938ebb01f9e6b7bcf24683b9661f91aab4108636207ba9dc6a2b9", size = 15237758 }, - { url = "https://files.pythonhosted.org/packages/29/bb/0accc6347df2f88efd092aa821eba46edebac726659a0160590989860b77/uv-0.4.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8cdadb99b842494a0a39e0184cacfb4af722fdbea3d4cb5ee3b25ea0b824292", size = 11925644 }, - { url = "https://files.pythonhosted.org/packages/a6/3d/32dfd30e22dca7ea76a1298d42cdda3c3e80be6763d9d87a14a5b9bbb38b/uv-0.4.6-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:081793fc66286ad0f9b939b5ab3239d20d486eff7b8f7c574d3fdcd44536595e", size = 11116370 }, - { url = "https://files.pythonhosted.org/packages/72/8a/18731ce4fae35a205efabd5f5f1979821fcb66f4d6ad6818e79b0b0bce20/uv-0.4.6-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:346db85ce897c6c782af33504922a84c583180906244ea224a306e2393f396f4", size = 10901947 }, - { url = "https://files.pythonhosted.org/packages/a7/08/665613bc0cb41f85afc1059b6b25815d5904020822d3a958986aa2d2eee6/uv-0.4.6-py3-none-musllinux_1_1_i686.whl", hash = "sha256:5d507dee4767d054171dcdbc1ac1fa7d15a7579e20ff988162c749f09a95f943", size = 11389509 }, - { url = "https://files.pythonhosted.org/packages/23/47/5a30dd313ce2c33c3637ea17c65fcddbfbf005fc456c6025f18e99bf56e8/uv-0.4.6-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:397e02640cbddc4230da8d614ef9a7138a024b9ce396f2a27013cd254e97480d", size = 13150151 }, - { url = "https://files.pythonhosted.org/packages/44/0e/37f4040363d05a0cca7f35759d34bb2ca10e9d89a647b8c6c3888ed8b643/uv-0.4.6-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:93165aa25f5278a0844c91a367140e725d384633946705651ff8e70757c2e92f", size = 12048785 }, - { url = "https://files.pythonhosted.org/packages/b4/1e/0b21ab16140d252d211411b4f61e2e448830f76b5cd5b88bb8dd827e5c7d/uv-0.4.6-py3-none-win32.whl", hash = "sha256:954f91be1b8e531e9fd3d6d549ec1638c20ce4e77dc6e272c5c5d21b8c952f11", size = 11320666 }, - { url = "https://files.pythonhosted.org/packages/d8/44/0231b506b5c2ea9da3242142fc7e53696060f548bb6f1cebca89268fa238/uv-0.4.6-py3-none-win_amd64.whl", hash = "sha256:86ecd19796363f0161600120d81ce7e3d17d54cce6d25017190daa608a8ab535", size = 12520653 }, + { url = "https://files.pythonhosted.org/packages/52/bf/142c1aefdb0cdb1200d8fd2193073d3b4b28028a7cacbce3fcaafe5fd9bf/uv-0.5.13-py3-none-linux_armv6l.whl", hash = "sha256:45301cb355fc0525e692d220ea7cb196e8378a53162b27d6eea6e65c7635ed3d", size = 14408033 }, + { url = "https://files.pythonhosted.org/packages/a0/3e/dc408e34fbb6e7bb5d1462dfeb765074c7951d400e31ba31c9b21ac46250/uv-0.5.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ff96602b7d391f35dc25122c2661e680a9e94864e96801611ef05c853826c82c", size = 14406050 }, + { url = "https://files.pythonhosted.org/packages/04/da/2e8cd58fb76c213a03c2fb556ad0858a6e585cd6e4b5f0e531ac81f113a8/uv-0.5.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:941c13f15a8726a2f5ad3fffa0bbe98e221c98fbe73adbca62cf327bd3fb029c", size = 13370750 }, + { url = "https://files.pythonhosted.org/packages/92/f1/4a0c9c1dbf6a237bd48fca67b9732e2d33e05536e2f54e8290c90e552ebc/uv-0.5.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:642d7e62c376487a63a03fb830749fb24dd7653f715864df2fb8788f29dfb85e", size = 13646567 }, + { url = "https://files.pythonhosted.org/packages/83/41/c39977fdc5eb6c2060a7705963460a0214452ee8d3f79bb8b96b3bbdaca2/uv-0.5.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5aab53db952f7f4505cfc2f62ecedb4a7977d746622f67cbadf052bef0d916e", size = 14172837 }, + { url = "https://files.pythonhosted.org/packages/d2/21/0823f2ac33febb103dfc51e0aa43c4540375b29689dfc846a897b1d704cb/uv-0.5.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f57250f46914affab4e4ca50822f1fbc7910df01818a22b7d91d4f5ccc5eb80c", size = 14907424 }, + { url = "https://files.pythonhosted.org/packages/82/51/04ed1d8e5cac1f3f26f20c9cb0202b1fad0bb3fb1c8c0ba320f82eb0b205/uv-0.5.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6fb26d2b6d4b6467b98acc22b67bbdd16360a1b843842d7cd77ff4df70884567", size = 15497699 }, + { url = "https://files.pythonhosted.org/packages/f7/b9/dd859a72bfde9c2daa7f64ebad699e4e75fda1e45dcf6ac8026f88296b55/uv-0.5.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:414dd7083bd7e06ab2db0ee6cfe81b0810c416e79ff1643701e15e2df5e1db2b", size = 15225898 }, + { url = "https://files.pythonhosted.org/packages/c0/bd/faed9861a27b9a24c0e93b5c18fbf0f4cc7a88e46bf15ad0fa03ffc7fb98/uv-0.5.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01fc5e928efba822ff28007f827c3c274b644508253fe358ec79085bae1da0c9", size = 19963452 }, + { url = "https://files.pythonhosted.org/packages/a7/64/00896d517e95621aa10e7a19dc6de636edab73f80b5e6ff4df73188731be/uv-0.5.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82479440765e507af1f2732bd496ec6ed849488f5ce310b8556cfe8c12da1c5f", size = 14970047 }, + { url = "https://files.pythonhosted.org/packages/d0/8f/f62f7fe20b7ead1e2afbe050932e698eb5ce6c2649fe49c2d2f96dc5fcba/uv-0.5.13-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:18f2141e71f6cb4c0ab44f1a100838d336f14c1d7a1c62444c79c2c2554331be", size = 13854500 }, + { url = "https://files.pythonhosted.org/packages/52/2b/efef56357acb6a63aab425f03c8d819eef7cd261a34bf8b6f64bc86a82d2/uv-0.5.13-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:4c2e75845c9c5adae3e8274967f70023b740488d732f88100baeef70090b60a0", size = 14178985 }, + { url = "https://files.pythonhosted.org/packages/e3/83/394d65c16d058eda1179c05418c68289f983aab2c278d06ea273e3e6299a/uv-0.5.13-py3-none-musllinux_1_1_i686.whl", hash = "sha256:6de38097d5efa86ae62a71ff268e16f7eab86f4afa63c32b546cb7f5a182874f", size = 14552142 }, + { url = "https://files.pythonhosted.org/packages/4b/6e/712477a76954f64bb6f0391c9dd1081e41c97d1f653c92688b1618e7fcdc/uv-0.5.13-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:30440409a28f1d5d34af8839a48ba9c26da06fc295f363ba9b12689b796453d4", size = 15088698 }, + { url = "https://files.pythonhosted.org/packages/7d/b6/a06fa33db44426275ab0ba87dc4a4e770acfab0897ee212a6ff4d3423e1d/uv-0.5.13-py3-none-win32.whl", hash = "sha256:df2a751e8319e11ef2d8bec30d549ee13949027aaa936ab2a0ab126602f4232b", size = 14459272 }, + { url = "https://files.pythonhosted.org/packages/a5/c8/b3bdc883e4ca0612ddd9f956d116308742f12d9140361dba6b2fcf66294d/uv-0.5.13-py3-none-win_amd64.whl", hash = "sha256:4219f1ed370bb2cec5f10dcc93fa9ecf5615fa67e0b71eef4817d571291f0bfc", size = 16315884 }, ] [[package]] name = "uvicorn" -version = "0.31.0" +version = "0.34.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0a/96/ee52d900f8e41cc35eaebfda76f3619c2e45b741f3ee957d6fe32be1b2aa/uvicorn-0.31.0.tar.gz", hash = "sha256:13bc21373d103859f68fe739608e2eb054a816dea79189bc3ca08ea89a275906", size = 77140 } +sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } wheels = [ - { url = "https://files.pythonhosted.org/packages/05/12/206aca5442524d16be7702d08b453d7c274c86fd759266b1f709d4ef43ba/uvicorn-0.31.0-py3-none-any.whl", hash = "sha256:cac7be4dd4d891c363cd942160a7b02e69150dcbc7a36be04d5f4af4b17c8ced", size = 63656 }, + { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, ] [[package]] @@ -1194,46 +1178,46 @@ wheels = [ [[package]] name = "watchfiles" -version = "0.24.0" +version = "1.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c8/27/2ba23c8cc85796e2d41976439b08d52f691655fdb9401362099502d1f0cf/watchfiles-0.24.0.tar.gz", hash = "sha256:afb72325b74fa7a428c009c1b8be4b4d7c2afedafb2982827ef2156646df2fe1", size = 37870 } +sdist = { url = "https://files.pythonhosted.org/packages/3c/7e/4569184ea04b501840771b8fcecee19b2233a8b72c196061263c0ef23c0b/watchfiles-1.0.3.tar.gz", hash = "sha256:f3ff7da165c99a5412fe5dd2304dd2dbaaaa5da718aad942dcb3a178eaa70c56", size = 38185 } wheels = [ - { url = "https://files.pythonhosted.org/packages/35/82/92a7bb6dc82d183e304a5f84ae5437b59ee72d48cee805a9adda2488b237/watchfiles-0.24.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7211b463695d1e995ca3feb38b69227e46dbd03947172585ecb0588f19b0d87a", size = 374137 }, - { url = "https://files.pythonhosted.org/packages/87/91/49e9a497ddaf4da5e3802d51ed67ff33024597c28f652b8ab1e7c0f5718b/watchfiles-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b8693502d1967b00f2fb82fc1e744df128ba22f530e15b763c8d82baee15370", size = 367733 }, - { url = "https://files.pythonhosted.org/packages/0d/d8/90eb950ab4998effea2df4cf3a705dc594f6bc501c5a353073aa990be965/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdab9555053399318b953a1fe1f586e945bc8d635ce9d05e617fd9fe3a4687d6", size = 437322 }, - { url = "https://files.pythonhosted.org/packages/6c/a2/300b22e7bc2a222dd91fce121cefa7b49aa0d26a627b2777e7bdfcf1110b/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:34e19e56d68b0dad5cff62273107cf5d9fbaf9d75c46277aa5d803b3ef8a9e9b", size = 433409 }, - { url = "https://files.pythonhosted.org/packages/99/44/27d7708a43538ed6c26708bcccdde757da8b7efb93f4871d4cc39cffa1cc/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:41face41f036fee09eba33a5b53a73e9a43d5cb2c53dad8e61fa6c9f91b5a51e", size = 452142 }, - { url = "https://files.pythonhosted.org/packages/b0/ec/c4e04f755be003129a2c5f3520d2c47026f00da5ecb9ef1e4f9449637571/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5148c2f1ea043db13ce9b0c28456e18ecc8f14f41325aa624314095b6aa2e9ea", size = 469414 }, - { url = "https://files.pythonhosted.org/packages/c5/4e/cdd7de3e7ac6432b0abf282ec4c1a1a2ec62dfe423cf269b86861667752d/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e4bd963a935aaf40b625c2499f3f4f6bbd0c3776f6d3bc7c853d04824ff1c9f", size = 472962 }, - { url = "https://files.pythonhosted.org/packages/27/69/e1da9d34da7fc59db358424f5d89a56aaafe09f6961b64e36457a80a7194/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c79d7719d027b7a42817c5d96461a99b6a49979c143839fc37aa5748c322f234", size = 425705 }, - { url = "https://files.pythonhosted.org/packages/e8/c1/24d0f7357be89be4a43e0a656259676ea3d7a074901f47022f32e2957798/watchfiles-0.24.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:32aa53a9a63b7f01ed32e316e354e81e9da0e6267435c7243bf8ae0f10b428ef", size = 612851 }, - { url = "https://files.pythonhosted.org/packages/c7/af/175ba9b268dec56f821639c9893b506c69fd999fe6a2e2c51de420eb2f01/watchfiles-0.24.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce72dba6a20e39a0c628258b5c308779b8697f7676c254a845715e2a1039b968", size = 594868 }, - { url = "https://files.pythonhosted.org/packages/44/81/1f701323a9f70805bc81c74c990137123344a80ea23ab9504a99492907f8/watchfiles-0.24.0-cp312-none-win32.whl", hash = "sha256:d9018153cf57fc302a2a34cb7564870b859ed9a732d16b41a9b5cb2ebed2d444", size = 264109 }, - { url = "https://files.pythonhosted.org/packages/b4/0b/32cde5bc2ebd9f351be326837c61bdeb05ad652b793f25c91cac0b48a60b/watchfiles-0.24.0-cp312-none-win_amd64.whl", hash = "sha256:551ec3ee2a3ac9cbcf48a4ec76e42c2ef938a7e905a35b42a1267fa4b1645896", size = 277055 }, - { url = "https://files.pythonhosted.org/packages/4b/81/daade76ce33d21dbec7a15afd7479de8db786e5f7b7d249263b4ea174e08/watchfiles-0.24.0-cp312-none-win_arm64.whl", hash = "sha256:b52a65e4ea43c6d149c5f8ddb0bef8d4a1e779b77591a458a893eb416624a418", size = 266169 }, + { url = "https://files.pythonhosted.org/packages/bf/a9/c8b5ab33444306e1a324cb2b51644f8458dd459e30c3841f925012893e6a/watchfiles-1.0.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:93436ed550e429da007fbafb723e0769f25bae178fbb287a94cb4ccdf42d3af3", size = 391395 }, + { url = "https://files.pythonhosted.org/packages/ad/d3/403af5f07359863c03951796ddab265ee8cce1a6147510203d0bf43950e7/watchfiles-1.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c18f3502ad0737813c7dad70e3e1cc966cc147fbaeef47a09463bbffe70b0a00", size = 381432 }, + { url = "https://files.pythonhosted.org/packages/f6/5f/921f2f2beabaf24b1ad81ac22bb69df8dd5771fdb68d6f34a5912a420941/watchfiles-1.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a5bc3ca468bb58a2ef50441f953e1f77b9a61bd1b8c347c8223403dc9b4ac9a", size = 441448 }, + { url = "https://files.pythonhosted.org/packages/63/d7/67d0d750b246f248ccdb400a85a253e93e419ea5b6cbe968fa48b97a5f30/watchfiles-1.0.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0d1ec043f02ca04bf21b1b32cab155ce90c651aaf5540db8eb8ad7f7e645cba8", size = 446852 }, + { url = "https://files.pythonhosted.org/packages/53/7c/d7cd94c7d0905f1e2f1c2232ea9bc39b1a48affd007e09c547ead96edb8f/watchfiles-1.0.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f58d3bfafecf3d81c15d99fc0ecf4319e80ac712c77cf0ce2661c8cf8bf84066", size = 471662 }, + { url = "https://files.pythonhosted.org/packages/26/81/738f8e66f7525753996b8aa292f78dcec1ef77887d62e6cdfb04cc2f352f/watchfiles-1.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1df924ba82ae9e77340101c28d56cbaff2c991bd6fe8444a545d24075abb0a87", size = 493765 }, + { url = "https://files.pythonhosted.org/packages/d2/50/78e21f5da24ab39114e9b24f7b0945ea1c6fc7bc9ae86cd87f8eaeb47325/watchfiles-1.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:632a52dcaee44792d0965c17bdfe5dc0edad5b86d6a29e53d6ad4bf92dc0ff49", size = 490558 }, + { url = "https://files.pythonhosted.org/packages/a8/93/1873fea6354b2858eae8970991d64e9a449d87726d596490d46bf00af8ed/watchfiles-1.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bf4b459d94a0387617a1b499f314aa04d8a64b7a0747d15d425b8c8b151da0", size = 442808 }, + { url = "https://files.pythonhosted.org/packages/4f/b4/2fc4c92fb28b029f66d04a4d430fe929284e9ff717b04bb7a3bb8a7a5605/watchfiles-1.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca94c85911601b097d53caeeec30201736ad69a93f30d15672b967558df02885", size = 615287 }, + { url = "https://files.pythonhosted.org/packages/1e/d4/93da24db39257e440240d338b617c5153ad11d361c34108f5c0e1e0743eb/watchfiles-1.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:65ab1fb635476f6170b07e8e21db0424de94877e4b76b7feabfe11f9a5fc12b5", size = 612812 }, + { url = "https://files.pythonhosted.org/packages/c6/67/9fd3661c2dc0309abd6021876653d91e8b64fb279529e2cadaa3520ef3e3/watchfiles-1.0.3-cp312-cp312-win32.whl", hash = "sha256:49bc1bc26abf4f32e132652f4b3bfeec77d8f8f62f57652703ef127e85a3e38d", size = 271642 }, + { url = "https://files.pythonhosted.org/packages/ae/aa/8c887edb78cd67f5d4d6a35c3aeb46d748643ebf962163130fb1871e2ee0/watchfiles-1.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:48681c86f2cb08348631fed788a116c89c787fdf1e6381c5febafd782f6c3b44", size = 285505 }, + { url = "https://files.pythonhosted.org/packages/7b/31/d212fa6390f0e73a91913ada0b925b294a78d67794795371208baf73f0b5/watchfiles-1.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:9e080cf917b35b20c889225a13f290f2716748362f6071b859b60b8847a6aa43", size = 277263 }, ] [[package]] name = "websockets" -version = "13.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e2/73/9223dbc7be3dcaf2a7bbf756c351ec8da04b1fa573edaf545b95f6b0c7fd/websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878", size = 158549 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/46/c426282f543b3c0296cf964aa5a7bb17e984f58dde23460c3d39b3148fcf/websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc", size = 157821 }, - { url = "https://files.pythonhosted.org/packages/aa/85/22529867010baac258da7c45848f9415e6cf37fef00a43856627806ffd04/websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49", size = 155480 }, - { url = "https://files.pythonhosted.org/packages/29/2c/bdb339bfbde0119a6e84af43ebf6275278698a2241c2719afc0d8b0bdbf2/websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd", size = 155715 }, - { url = "https://files.pythonhosted.org/packages/9f/d0/8612029ea04c5c22bf7af2fd3d63876c4eaeef9b97e86c11972a43aa0e6c/websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0", size = 165647 }, - { url = "https://files.pythonhosted.org/packages/56/04/1681ed516fa19ca9083f26d3f3a302257e0911ba75009533ed60fbb7b8d1/websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6", size = 164592 }, - { url = "https://files.pythonhosted.org/packages/38/6f/a96417a49c0ed132bb6087e8e39a37db851c70974f5c724a4b2a70066996/websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9", size = 165012 }, - { url = "https://files.pythonhosted.org/packages/40/8b/fccf294919a1b37d190e86042e1a907b8f66cff2b61e9befdbce03783e25/websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68", size = 165311 }, - { url = "https://files.pythonhosted.org/packages/c1/61/f8615cf7ce5fe538476ab6b4defff52beb7262ff8a73d5ef386322d9761d/websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14", size = 164692 }, - { url = "https://files.pythonhosted.org/packages/5c/f1/a29dd6046d3a722d26f182b783a7997d25298873a14028c4760347974ea3/websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf", size = 164686 }, - { url = "https://files.pythonhosted.org/packages/0f/99/ab1cdb282f7e595391226f03f9b498f52109d25a2ba03832e21614967dfa/websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c", size = 158712 }, - { url = "https://files.pythonhosted.org/packages/46/93/e19160db48b5581feac8468330aa11b7292880a94a37d7030478596cc14e/websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3", size = 159145 }, - { url = "https://files.pythonhosted.org/packages/56/27/96a5cd2626d11c8280656c6c71d8ab50fe006490ef9971ccd154e0c42cd2/websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f", size = 152134 }, +version = "14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/1b/380b883ce05bb5f45a905b61790319a28958a9ab1e4b6b95ff5464b60ca1/websockets-14.1.tar.gz", hash = "sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8", size = 162840 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/64/55698544ce29e877c9188f1aee9093712411a8fc9732cca14985e49a8e9c/websockets-14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed", size = 161957 }, + { url = "https://files.pythonhosted.org/packages/a2/b1/b088f67c2b365f2c86c7b48edb8848ac27e508caf910a9d9d831b2f343cb/websockets-14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d", size = 159620 }, + { url = "https://files.pythonhosted.org/packages/c1/89/2a09db1bbb40ba967a1b8225b07b7df89fea44f06de9365f17f684d0f7e6/websockets-14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707", size = 159852 }, + { url = "https://files.pythonhosted.org/packages/ca/c1/f983138cd56e7d3079f1966e81f77ce6643f230cd309f73aa156bb181749/websockets-14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a", size = 169675 }, + { url = "https://files.pythonhosted.org/packages/c1/c8/84191455d8660e2a0bdb33878d4ee5dfa4a2cedbcdc88bbd097303b65bfa/websockets-14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45", size = 168619 }, + { url = "https://files.pythonhosted.org/packages/8d/a7/62e551fdcd7d44ea74a006dc193aba370505278ad76efd938664531ce9d6/websockets-14.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3dfff83ca578cada2d19e665e9c8368e1598d4e787422a460ec70e531dbdd58", size = 169042 }, + { url = "https://files.pythonhosted.org/packages/ad/ed/1532786f55922c1e9c4d329608e36a15fdab186def3ca9eb10d7465bc1cc/websockets-14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058", size = 169345 }, + { url = "https://files.pythonhosted.org/packages/ea/fb/160f66960d495df3de63d9bcff78e1b42545b2a123cc611950ffe6468016/websockets-14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4", size = 168725 }, + { url = "https://files.pythonhosted.org/packages/cf/53/1bf0c06618b5ac35f1d7906444b9958f8485682ab0ea40dee7b17a32da1e/websockets-14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05", size = 168712 }, + { url = "https://files.pythonhosted.org/packages/e5/22/5ec2f39fff75f44aa626f86fa7f20594524a447d9c3be94d8482cd5572ef/websockets-14.1-cp312-cp312-win32.whl", hash = "sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0", size = 162838 }, + { url = "https://files.pythonhosted.org/packages/74/27/28f07df09f2983178db7bf6c9cccc847205d2b92ced986cd79565d68af4f/websockets-14.1-cp312-cp312-win_amd64.whl", hash = "sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f", size = 163277 }, + { url = "https://files.pythonhosted.org/packages/b0/0b/c7e5d11020242984d9d37990310520ed663b942333b83a033c2f20191113/websockets-14.1-py3-none-any.whl", hash = "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e", size = 156277 }, ] [[package]] diff --git a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml index 3ede4246a6..fe6053f320 100644 --- a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml +++ b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml @@ -1,5 +1,6 @@ exclude: '^docs/|/migrations/|devcontainer.json' default_stages: [pre-commit] +minimum_pre_commit_version: "3.2.0" default_language_version: python: python3.12 @@ -28,14 +29,14 @@ repos: exclude: '{{cookiecutter.project_slug}}/templates/|node_modules/|.*\.min\.(js|css)$' - repo: https://github.com/adamchainz/django-upgrade - rev: '1.22.1' + rev: '1.22.2' hooks: - id: django-upgrade args: ['--target-version', '5.0'] # Run the Ruff linter. - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.1 + rev: v0.9.2 hooks: # Linter - id: ruff @@ -44,7 +45,7 @@ repos: - id: ruff-format - repo: https://github.com/Riverside-Healthcare/djLint - rev: v1.35.4 + rev: v1.36.4 hooks: - id: djlint-reformat-django - id: djlint-django diff --git a/{{cookiecutter.project_slug}}/compose/local/django/Dockerfile b/{{cookiecutter.project_slug}}/compose/local/django/Dockerfile index d892c9dca1..b8ff85977a 100644 --- a/{{cookiecutter.project_slug}}/compose/local/django/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/local/django/Dockerfile @@ -1,5 +1,5 @@ # define an alias for the specific python version used in this file. -FROM docker.io/python:3.12.7-slim-bookworm AS python +FROM docker.io/python:3.12.8-slim-bookworm AS python # Python build stage FROM python AS python-build-stage diff --git a/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile b/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile index 40caf85117..ba9e579fd7 100644 --- a/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile @@ -1,5 +1,5 @@ # define an alias for the specific python version used in this file. -FROM docker.io/python:3.12.7-slim-bookworm AS python +FROM docker.io/python:3.12.8-slim-bookworm AS python # Python build stage diff --git a/{{cookiecutter.project_slug}}/compose/local/node/Dockerfile b/{{cookiecutter.project_slug}}/compose/local/node/Dockerfile index b0142ff81f..64ef9758b9 100644 --- a/{{cookiecutter.project_slug}}/compose/local/node/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/local/node/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/node:22-bookworm-slim +FROM docker.io/node:22.13-bookworm-slim WORKDIR /app diff --git a/{{cookiecutter.project_slug}}/compose/production/aws/Dockerfile b/{{cookiecutter.project_slug}}/compose/production/aws/Dockerfile index 5a6be94dab..9c66f69c2f 100644 --- a/{{cookiecutter.project_slug}}/compose/production/aws/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/production/aws/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/amazon/aws-cli:2.19.0 +FROM docker.io/amazon/aws-cli:2.23.0 # Clear entrypoint from the base image, otherwise it's always calling the aws CLI ENTRYPOINT [] diff --git a/{{cookiecutter.project_slug}}/compose/production/django/Dockerfile b/{{cookiecutter.project_slug}}/compose/production/django/Dockerfile index d8eee7a849..68b427eca7 100644 --- a/{{cookiecutter.project_slug}}/compose/production/django/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/production/django/Dockerfile @@ -25,7 +25,7 @@ RUN npm run build {%- endif %} # define an alias for the specific python version used in this file. -FROM docker.io/python:3.12.7-slim-bookworm AS python +FROM docker.io/python:3.12.8-slim-bookworm AS python # Python build stage FROM python AS python-build-stage diff --git a/{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile b/{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile index e5bc937a7a..c9a5043676 100644 --- a/{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/traefik:3.2.0 +FROM docker.io/traefik:3.3.2 RUN mkdir -p /etc/traefik/acme \ && touch /etc/traefik/acme/acme.json \ && chmod 600 /etc/traefik/acme/acme.json diff --git a/{{cookiecutter.project_slug}}/config/celery_app.py b/{{cookiecutter.project_slug}}/config/celery_app.py index 0728a649e0..836429078a 100644 --- a/{{cookiecutter.project_slug}}/config/celery_app.py +++ b/{{cookiecutter.project_slug}}/config/celery_app.py @@ -1,6 +1,7 @@ import os from celery import Celery +from celery.signals import setup_logging # set the default Django settings module for the 'celery' program. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") @@ -13,5 +14,15 @@ # should have a `CELERY_` prefix. app.config_from_object("django.conf:settings", namespace="CELERY") + +@setup_logging.connect +def config_loggers(*args, **kwargs): + from logging.config import dictConfig + + from django.conf import settings + + dictConfig(settings.LOGGING) + + # Load task modules from all registered Django app configs. app.autodiscover_tasks() diff --git a/{{cookiecutter.project_slug}}/config/settings/base.py b/{{cookiecutter.project_slug}}/config/settings/base.py index e7cc4c8db5..4a740774c3 100644 --- a/{{cookiecutter.project_slug}}/config/settings/base.py +++ b/{{cookiecutter.project_slug}}/config/settings/base.py @@ -3,6 +3,9 @@ import re {%- if cookiecutter.use_simplejwt == "y" %} from datetime import timedelta + +{% if cookiecutter.use_celery == 'y' -%} +import ssl {%- endif %} from pathlib import Path @@ -347,6 +350,7 @@ } REDIS_URL = env("REDIS_URL", default="redis://{% if cookiecutter.use_docker == 'y' %}redis{%else%}localhost{% endif %}:6379/0") +REDIS_SSL = REDIS_URL.startswith("rediss://") {% if cookiecutter.use_celery == 'y' -%} # Celery @@ -356,8 +360,12 @@ CELERY_TIMEZONE = TIME_ZONE # https://docs.celeryq.dev/en/stable/userguide/configuration.html#std:setting-broker_url CELERY_BROKER_URL = REDIS_URL +# https://docs.celeryq.dev/en/stable/userguide/configuration.html#redis-backend-use-ssl +CELERY_BROKER_USE_SSL = {"ssl_cert_reqs": ssl.CERT_NONE} if REDIS_SSL else None # https://docs.celeryq.dev/en/stable/userguide/configuration.html#std:setting-result_backend CELERY_RESULT_BACKEND = REDIS_URL +# https://docs.celeryq.dev/en/stable/userguide/configuration.html#redis-backend-use-ssl +CELERY_REDIS_BACKEND_USE_SSL = CELERY_BROKER_USE_SSL # https://docs.celeryq.dev/en/stable/userguide/configuration.html#result-extended CELERY_RESULT_EXTENDED = True # https://docs.celeryq.dev/en/stable/userguide/configuration.html#result-backend-always-retry @@ -383,6 +391,8 @@ CELERY_WORKER_SEND_TASK_EVENTS = True # https://docs.celeryq.dev/en/stable/userguide/configuration.html#std-setting-task_send_sent_event CELERY_TASK_SEND_SENT_EVENT = True +# https://docs.celeryq.dev/en/stable/userguide/configuration.html#worker-hijack-root-logger +CELERY_WORKER_HIJACK_ROOT_LOGGER = False # https://docs.celeryproject.org/en/stable/django/first-steps-with-django.html CELERY_RESULT_BACKEND = "django-db" diff --git a/{{cookiecutter.project_slug}}/gulpfile.js b/{{cookiecutter.project_slug}}/gulpfile.mjs similarity index 76% rename from {{cookiecutter.project_slug}}/gulpfile.js rename to {{cookiecutter.project_slug}}/gulpfile.mjs index 8c819b3c27..fabe4f0d33 100644 --- a/{{cookiecutter.project_slug}}/gulpfile.js +++ b/{{cookiecutter.project_slug}}/gulpfile.mjs @@ -3,28 +3,32 @@ //////////////////////////////// // Gulp and package -const { src, dest, parallel, series, watch } = require('gulp'); -const pjson = require('./package.json'); +import { src, dest, parallel, series, task, watch } from 'gulp'; +import pjson from './package.json' with {type: 'json'}; // Plugins -const autoprefixer = require('autoprefixer'); -const browserSync = require('browser-sync').create(); -const concat = require('gulp-concat'); -const tildeImporter = require('node-sass-tilde-importer'); -const cssnano = require('cssnano'); -const imagemin = require('gulp-imagemin'); -const pixrem = require('pixrem'); -const plumber = require('gulp-plumber'); -const postcss = require('gulp-postcss'); +import autoprefixer from 'autoprefixer'; +import browserSyncLib from 'browser-sync'; +import concat from 'gulp-concat'; +import tildeImporter from 'node-sass-tilde-importer'; +import cssnano from 'cssnano'; +import pixrem from 'pixrem'; +import plumber from 'gulp-plumber'; +import postcss from 'gulp-postcss'; +import rename from 'gulp-rename'; +import gulpSass from 'gulp-sass'; +import * as dartSass from 'sass'; +import gulUglifyES from 'gulp-uglify-es'; +import { spawn } from 'node:child_process'; + +const browserSync = browserSyncLib.create(); const reload = browserSync.reload; -const rename = require('gulp-rename'); -const sass = require('gulp-sass')(require('sass')); -const spawn = require('child_process').spawn; -const uglify = require('gulp-uglify-es').default; +const sass = gulpSass(dartSass); +const uglify = gulUglifyES.default; // Relative paths function -function pathsConfig(appName) { - this.app = `./${pjson.name}`; +function pathsConfig() { + const appName = `./${pjson.name}`; const vendorsRoot = 'node_modules'; return { @@ -32,13 +36,13 @@ function pathsConfig(appName) { `${vendorsRoot}/@popperjs/core/dist/umd/popper.js`, `${vendorsRoot}/bootstrap/dist/js/bootstrap.js`, ], - app: this.app, - templates: `${this.app}/templates`, - css: `${this.app}/static/css`, - sass: `${this.app}/static/sass`, - fonts: `${this.app}/static/fonts`, - images: `${this.app}/static/images`, - js: `${this.app}/static/js`, + app: appName, + templates: `${appName}/templates`, + css: `${appName}/static/css`, + sass: `${appName}/static/sass`, + fonts: `${appName}/static/fonts`, + images: `${appName}/static/images`, + js: `${appName}/static/js`, }; } @@ -95,7 +99,8 @@ function vendorScripts() { } // Image compression -function imgCompression() { +async function imgCompression() { + const imagemin = (await import("gulp-imagemin")).default; return src(`${paths.images}/*`) .pipe(imagemin()) // Compresses PNG, JPEG, GIF and SVG images .pipe(dest(paths.images)); @@ -163,7 +168,7 @@ function watchPaths() { } // Generate all assets -const generateAssets = parallel(styles, scripts, vendorScripts, imgCompression); +const build = parallel(styles, scripts, vendorScripts, imgCompression); // Set up dev environment {%- if cookiecutter.use_docker == 'n' %} @@ -176,6 +181,6 @@ const dev = parallel(runServer, initBrowserSync, watchPaths); const dev = parallel(initBrowserSync, watchPaths); {%- endif %} -exports.default = series(generateAssets, dev); -exports['generate-assets'] = generateAssets; -exports['dev'] = dev; +task('default', series(build, dev)); +task('build', build); +task('dev', dev); diff --git a/{{cookiecutter.project_slug}}/justfile b/{{cookiecutter.project_slug}}/justfile new file mode 100644 index 0000000000..38ef8dd47f --- /dev/null +++ b/{{cookiecutter.project_slug}}/justfile @@ -0,0 +1,38 @@ +export COMPOSE_FILE := "docker-compose.local.yml" + +## Just does not yet manage signals for subprocesses reliably, which can lead to unexpected behavior. +## Exercise caution before expanding its usage in production environments. +## For more information, see https://github.com/casey/just/issues/2473 . + + +# Default command to list all available commands. +default: + @just --list + +# build: Build python image. +build: + @echo "Building python image..." + @docker compose build + +# up: Start up containers. +up: + @echo "Starting up containers..." + @docker compose up -d --remove-orphans + +# down: Stop containers. +down: + @echo "Stopping containers..." + @docker compose down + +# prune: Remove containers and their volumes. +prune *args: + @echo "Killing containers and removing volumes..." + @docker compose down -v {{ "{{args}}" }} + +# logs: View container logs +logs *args: + @docker compose logs -f {{ "{{args}}" }} + +# manage: Executes `manage.py` command. +manage +args: + @docker compose run --rm django python ./manage.py {{ "{{args}}" }} diff --git a/{{cookiecutter.project_slug}}/locale/README.md b/{{cookiecutter.project_slug}}/locale/README.md index 7cb6876ad5..9ee59d3ef1 100644 --- a/{{cookiecutter.project_slug}}/locale/README.md +++ b/{{cookiecutter.project_slug}}/locale/README.md @@ -1,6 +1,6 @@ # Translations -Start by configuring the `LANGUAGES` settings in `base.py`, by uncommenting languages you are willing to support. Then, translations strings will be placed in this folder when running: +Start by configuring the `LANGUAGES` settings in `base.py`, by uncommenting languages you are willing to support. Then, translation strings will be placed in this folder when running: ```bash {% if cookiecutter.use_docker == 'y' %}docker compose -f docker-compose.local.yml run --rm django {% endif %}python manage.py makemessages --all --no-location @@ -19,7 +19,7 @@ Once all translations are done, they need to be compiled into `.mo` files (stand {% if cookiecutter.use_docker == 'y' %}docker compose -f docker-compose.local.yml run --rm django {% endif %}python manage.py compilemessages ``` -Note that the `.po` files are NOT used by the application directly, so if the `.mo` files are out of dates, the content won't appear as translated even if the `.po` files are up-to-date. +Note that the `.po` files are NOT used by the application directly, so if the `.mo` files are out of date, the content won't appear as translated even if the `.po` files are up-to-date. ## Production diff --git a/{{cookiecutter.project_slug}}/package.json b/{{cookiecutter.project_slug}}/package.json index 94861c4eb3..11c41cc71d 100644 --- a/{{cookiecutter.project_slug}}/package.json +++ b/{{cookiecutter.project_slug}}/package.json @@ -13,8 +13,8 @@ "gulp-concat": "^2.6.1", "concurrently": "^9.0.0", "cssnano": "^7.0.0", - "gulp": "^4.0.2", - "gulp-imagemin": "^7.1.0", + "gulp": "^5.0.0", + "gulp-imagemin": "^9.1.0", "gulp-plumber": "^1.2.1", "gulp-postcss": "^10.0.0", "gulp-rename": "^2.0.0", @@ -26,16 +26,16 @@ "postcss": "^8.3.11", "postcss-loader": "^8.0.0", "postcss-preset-env": "^10.0.3", - "sass": "^1.43.4", + "sass": "1.77.6", "sass-loader": "^16.0.1", - "webpack": "^5.65.0", + "webpack": "^5.82.0", "webpack-bundle-tracker": "^3.0.1", - "webpack-cli": "^5.0.1", + "webpack-cli": "^6.0.1", "webpack-dev-server": "^5.0.2", "webpack-merge": "^6.0.1" }, "engines": { - "node": "22" + "node": "22.13" }, "browserslist": [ "last 2 versions" diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index c0d150b52f..e5df0fd63c 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -1,5 +1,5 @@ python-slugify==8.0.4 # https://github.com/un33k/python-slugify -Pillow==11.0.0 # https://github.com/python-pillow/Pillow +Pillow==11.1.0 # https://github.com/python-pillow/Pillow {%- if cookiecutter.frontend_pipeline == 'Django Compressor' %} {%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %} rcssmin==1.1.2 --install-option="--without-c-extensions" # https://github.com/ndparker/rcssmin @@ -11,9 +11,9 @@ argon2-cffi==23.1.0 # https://github.com/hynek/argon2_cffi {%- if cookiecutter.use_whitenoise == 'y' %} whitenoise==6.8.2 # https://github.com/evansd/whitenoise {%- endif %} -redis==5.2.0 # https://github.com/redis/redis-py +redis==5.2.1 # https://github.com/redis/redis-py {%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %} -hiredis==3.0.0 # https://github.com/redis/hiredis-py +hiredis==3.1.0 # https://github.com/redis/hiredis-py {%- endif %} {%- if cookiecutter.use_celery == "y" %} celery==5.4.0 # pyup: < 6.0 # https://github.com/celery/celery @@ -23,16 +23,16 @@ flower==2.0.1 # https://github.com/mher/flower {%- endif %} {%- endif %} {%- if cookiecutter.use_async == 'y' %} -uvicorn[standard]==0.32.0 # https://github.com/encode/uvicorn -uvicorn-worker==0.2.0 # https://github.com/Kludex/uvicorn-worker +uvicorn[standard]==0.34.0 # https://github.com/encode/uvicorn +uvicorn-worker==0.3.0 # https://github.com/Kludex/uvicorn-worker {%- endif %} # Django # ------------------------------------------------------------------------------ -django==5.0.9 # pyup: < 5.1 # https://www.djangoproject.com/ -django-environ==0.11.2 # https://github.com/joke2k/django-environ +django==5.0.11 # pyup: < 5.1 # https://www.djangoproject.com/ +django-environ==0.12.0 # https://github.com/joke2k/django-environ django-model-utils==5.0.0 # https://github.com/jazzband/django-model-utils -django-allauth[mfa]==65.1.0 # https://github.com/pennersr/django-allauth +django-allauth[mfa]==65.3.1 # https://github.com/pennersr/django-allauth django-crispy-forms==2.3 # https://github.com/django-crispy-forms/django-crispy-forms crispy-bootstrap5==2024.10 # https://github.com/django-crispy-forms/crispy-bootstrap5 {%- if cookiecutter.frontend_pipeline == 'Django Compressor' %} @@ -44,7 +44,7 @@ django-redis==5.4.0 # https://github.com/jazzband/django-redis djangorestframework==3.15.2 # https://github.com/encode/django-rest-framework django-cors-headers==4.6.0 # https://github.com/adamchainz/django-cors-headers # DRF-spectacular for api documentation -drf-spectacular==0.27.2 # https://github.com/tfranzel/drf-spectacular +drf-spectacular==0.28.0 # https://github.com/tfranzel/drf-spectacular {%- endif %} {%- if cookiecutter.frontend_pipeline == 'Webpack' %} django-webpack-loader==3.1.1 # https://github.com/django-webpack/django-webpack-loader diff --git a/{{cookiecutter.project_slug}}/requirements/local.txt b/{{cookiecutter.project_slug}}/requirements/local.txt index 03e6c3e079..bf4b1f8c8a 100644 --- a/{{cookiecutter.project_slug}}/requirements/local.txt +++ b/{{cookiecutter.project_slug}}/requirements/local.txt @@ -1,24 +1,24 @@ -r production.txt -Werkzeug[watchdog]==3.0.6 # https://github.com/pallets/werkzeug +Werkzeug[watchdog]==3.1.3 # https://github.com/pallets/werkzeug ipdb==0.13.13 # https://github.com/gotcha/ipdb {%- if cookiecutter.use_docker == 'y' %} -psycopg[c]==3.2.3 # https://github.com/psycopg/psycopg +psycopg[c]==3.2.4 # https://github.com/psycopg/psycopg {%- else %} -psycopg[binary]==3.2.3 # https://github.com/psycopg/psycopg +psycopg[binary]==3.2.4 # https://github.com/psycopg/psycopg {%- endif %} {%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %} -watchfiles==0.24.0 # https://github.com/samuelcolvin/watchfiles +watchfiles==1.0.4 # https://github.com/samuelcolvin/watchfiles {%- endif %} # Testing # ------------------------------------------------------------------------------ mypy==1.13.0 # https://github.com/python/mypy -django-stubs[compatible-mypy]==5.1.1 # https://github.com/typeddjango/django-stubs -pytest==8.3.3 # https://github.com/pytest-dev/pytest +django-stubs[compatible-mypy]==5.1.2 # https://github.com/typeddjango/django-stubs +pytest==8.3.4 # https://github.com/pytest-dev/pytest pytest-sugar==1.0.0 # https://github.com/Frozenball/pytest-sugar {%- if cookiecutter.use_drf == "y" %} -djangorestframework-stubs==3.15.1 # https://github.com/typeddjango/djangorestframework-stubs +djangorestframework-stubs==3.15.2 # https://github.com/typeddjango/djangorestframework-stubs {%- endif %} # Documentation @@ -28,16 +28,16 @@ sphinx-autobuild==2024.10.3 # https://github.com/GaretJax/sphinx-autobuild # Code quality # ------------------------------------------------------------------------------ -ruff==0.7.1 # https://github.com/astral-sh/ruff -coverage==7.6.4 # https://github.com/nedbat/coveragepy -djlint==1.35.4 # https://github.com/Riverside-Healthcare/djLint +ruff==0.9.2 # https://github.com/astral-sh/ruff +coverage==7.6.10 # https://github.com/nedbat/coveragepy +djlint==1.36.4 # https://github.com/Riverside-Healthcare/djLint pre-commit==4.0.1 # https://github.com/pre-commit/pre-commit # Django # ------------------------------------------------------------------------------ factory-boy==3.3.1 # https://github.com/FactoryBoy/factory_boy -django-debug-toolbar==4.4.6 # https://github.com/jazzband/django-debug-toolbar +django-debug-toolbar==5.0.1 # https://github.com/jazzband/django-debug-toolbar django-extensions==3.2.3 # https://github.com/django-extensions/django-extensions django-coverage-plugin==3.1.0 # https://github.com/nedbat/django_coverage_plugin pytest-django==4.9.0 # https://github.com/pytest-dev/pytest-django diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index b6f22db451..9dc093bcd9 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -3,15 +3,15 @@ -r base.txt gunicorn==23.0.0 # https://github.com/benoitc/gunicorn -psycopg[c]==3.2.3 # https://github.com/psycopg/psycopg +psycopg[c]==3.2.4 # https://github.com/psycopg/psycopg {%- if cookiecutter.use_whitenoise == 'n'and cookiecutter.cloud_provider in ('AWS', 'GCP') %} -Collectfasta==3.2.0 # https://github.com/jasongi/collectfasta +Collectfasta==3.2.1 # https://github.com/jasongi/collectfasta {%- endif %} {%- if cookiecutter.use_sentry == "y" %} -sentry-sdk==2.17.0 # https://github.com/getsentry/sentry-python +sentry-sdk==2.20.0 # https://github.com/getsentry/sentry-python {%- endif %} {%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %} -hiredis==3.0.0 # https://github.com/redis/hiredis-py +hiredis==3.1.0 # https://github.com/redis/hiredis-py {%- endif %} # Django