diff --git a/.codecov.yml b/.codecov.yml
new file mode 100644
index 0000000000..2da2f923b0
--- /dev/null
+++ b/.codecov.yml
@@ -0,0 +1,55 @@
+codecov:
+ require_ci_to_pass: true
+
+comment:
+ layout: reach, diff, flags, files, footer
+ behavior: default
+ require_changes: false
+
+coverage:
+ status:
+ project:
+ default:
+ target: auto
+ threshold: 1%
+ base: auto
+ backend:
+ flags:
+ - backend
+ target: 80%
+ threshold: 1%
+ base: auto
+ frontend:
+ flags:
+ - frontend
+ target: 80%
+ threshold: 1%
+ base: auto
+ patch:
+ default:
+ target: auto
+ threshold: 0%
+ backend:
+ flags:
+ - backend
+ target: auto
+ threshold: 0%
+ frontend:
+ flags:
+ - frontend
+ target: auto
+ threshold: 0%
+
+fixes:
+ - /app/::frontend/
+ - /home/owasp/::backend/
+
+flags:
+ backend:
+ paths:
+ - backend/
+ carryforward: true
+ frontend:
+ paths:
+ - frontend/
+ carryforward: true
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 26898ec789..69c0abf597 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -40,6 +40,11 @@ updates:
schedule:
interval: daily
+ - package-ecosystem: docker
+ directory: /docker/semgrep
+ schedule:
+ interval: daily
+
- package-ecosystem: github-actions
directory: /
schedule:
diff --git a/.github/workflows/check-pr-issue.yaml b/.github/workflows/check-pr-issue.yaml
index b906449e9f..f05c6d3101 100644
--- a/.github/workflows/check-pr-issue.yaml
+++ b/.github/workflows/check-pr-issue.yaml
@@ -15,8 +15,10 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ # NOSEMGREP: yaml.github-actions.security.pull-request-target-code-checkout.pull-request-target-code-checkout
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
+ # Explicitly checking out base branch (target repository), not PR code.
ref: ${{ github.event.pull_request.base.sha }}
- name: Check PR linked issue and assignee
diff --git a/.github/workflows/run-ci-cd.yaml b/.github/workflows/run-ci-cd.yaml
index 3501b3c4ed..d2dca23917 100644
--- a/.github/workflows/run-ci-cd.yaml
+++ b/.github/workflows/run-ci-cd.yaml
@@ -32,20 +32,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Install Poetry
run: pipx install poetry
- name: Set up Python
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
cache: 'poetry'
cache-dependency-path: backend/poetry.lock
python-version: '3.13'
- name: Set up pre-commit cache
- uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb
+ uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
@@ -78,7 +78,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Install pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061
@@ -113,7 +113,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
@@ -143,7 +143,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Trivy
uses: aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514
@@ -169,7 +169,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Trivy
uses: aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514
@@ -184,17 +184,44 @@ jobs:
trivy-config: trivy.yaml
timeout-minutes: 5
+ run-security-scan:
+ name: Run security scan
+ needs:
+ - check-frontend
+ - pre-commit
+ - spellcheck
+ permissions:
+ contents: read
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
+
+ - name: Run Security CI Scan
+ run: make security-scan
+
+ - name: Upload security scan report
+ if: always()
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
+ with:
+ name: semgrep-results-run-${{ github.run_number }}
+ path: semgrep-security-report.txt
+ retention-days: 14
+ timeout-minutes: 5
+
run-backend-tests:
name: Run backend tests
needs:
+ - run-security-scan
- scan-code
- scan-ci-dependencies
permissions:
contents: read
+ id-token: write
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
@@ -215,20 +242,38 @@ jobs:
- name: Run backend tests
run: |
- docker run -e DJANGO_SETTINGS_MODULE=settings.test --env-file backend/.env.example owasp/nest:test-backend-latest pytest
+ CONTAINER_ID=$(docker create \
+ -e DJANGO_SETTINGS_MODULE=settings.test \
+ --env-file backend/.env.example \
+ owasp/nest:test-backend-latest pytest)
+ docker start -a $CONTAINER_ID
+ EXIT_CODE=$?
+ docker cp $CONTAINER_ID:/home/owasp/coverage.xml backend/coverage.xml 2>/dev/null || true
+ docker rm $CONTAINER_ID >/dev/null 2>&1
+ exit $EXIT_CODE
+
+ - name: Upload coverage report to Codecov
+ uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de
+ with:
+ fail_ci_if_error: false
+ files: backend/coverage.xml
+ flags: backend
+ use_oidc: true
timeout-minutes: 5
run-frontend-unit-tests:
name: Run frontend unit tests
needs:
+ - run-security-scan
- scan-code
- scan-ci-dependencies
permissions:
contents: read
+ id-token: write
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
@@ -249,12 +294,28 @@ jobs:
- name: Run frontend unit tests
run: |
- docker run --env-file frontend/.env.example owasp/nest:test-frontend-unit-latest pnpm run test:unit
+ CONTAINER_ID=$(docker create \
+ --env-file frontend/.env.example \
+ owasp/nest:test-frontend-unit-latest pnpm run test:unit)
+ docker start -a $CONTAINER_ID
+ EXIT_CODE=$?
+ docker cp $CONTAINER_ID:/app/coverage frontend/coverage 2>/dev/null || true
+ docker rm $CONTAINER_ID >/dev/null 2>&1
+ exit $EXIT_CODE
+
+ - name: Upload coverage report to Codecov
+ uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de
+ with:
+ fail_ci_if_error: false
+ files: frontend/coverage/lcov.info
+ flags: frontend
+ use_oidc: true
timeout-minutes: 5
run-frontend-e2e-tests:
name: Run frontend e2e tests
needs:
+ - run-security-scan
- scan-code
- scan-ci-dependencies
permissions:
@@ -285,7 +346,7 @@ jobs:
- 6379:6379
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
@@ -342,11 +403,12 @@ jobs:
- name: Run frontend end-to-end tests
run: |
docker run --env-file frontend/.env.e2e.example owasp/nest:test-frontend-e2e-latest pnpm run test:e2e
- timeout-minutes: 10
+ timeout-minutes: 15
run-frontend-a11y-tests:
name: Run frontend accessibility tests
needs:
+ - run-security-scan
- scan-code
- scan-ci-dependencies
permissions:
@@ -354,7 +416,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
@@ -397,7 +459,9 @@ jobs:
run-graphql-fuzz-tests:
name: Run GraphQL fuzz tests
+ if: false
needs:
+ - run-security-scan
- scan-code
- scan-ci-dependencies
uses: ./.github/workflows/run-fuzz-tests.yaml
@@ -407,6 +471,7 @@ jobs:
run-rest-fuzz-tests:
name: Run REST fuzz tests
needs:
+ - run-security-scan
- scan-code
- scan-ci-dependencies
uses: ./.github/workflows/run-fuzz-tests.yaml
@@ -433,7 +498,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130
@@ -557,7 +622,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Trivy
uses: aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514
@@ -601,7 +666,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708
@@ -701,7 +766,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708
@@ -869,7 +934,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Install pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061
@@ -901,7 +966,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Run baseline scan
uses: zaproxy/action-baseline@de8ad967d3548d44ef623df22cf95c3b0baf8b25
@@ -939,7 +1004,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130
@@ -1045,7 +1110,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Trivy
uses: aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514
@@ -1090,7 +1155,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Prepare SSH key
env:
@@ -1218,7 +1283,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Prepare SSH key
env:
@@ -1246,7 +1311,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Run baseline scan
uses: zaproxy/action-baseline@de8ad967d3548d44ef623df22cf95c3b0baf8b25
diff --git a/.github/workflows/run-code-ql.yaml b/.github/workflows/run-code-ql.yaml
index 6c756cbc1d..3ab53ce305 100644
--- a/.github/workflows/run-code-ql.yaml
+++ b/.github/workflows/run-code-ql.yaml
@@ -28,7 +28,7 @@ jobs:
- python
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Initialize CodeQL
uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89
diff --git a/.github/workflows/run-fuzz-tests.yaml b/.github/workflows/run-fuzz-tests.yaml
index 0de9a396b2..a299f73573 100644
--- a/.github/workflows/run-fuzz-tests.yaml
+++ b/.github/workflows/run-fuzz-tests.yaml
@@ -43,7 +43,7 @@ jobs:
- 6379:6379
steps:
- name: Check out repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
diff --git a/.github/workflows/update-nest-test-images.yaml b/.github/workflows/update-nest-test-images.yaml
index 8c0bb4a0c8..5fa11c01d1 100644
--- a/.github/workflows/update-nest-test-images.yaml
+++ b/.github/workflows/update-nest-test-images.yaml
@@ -19,7 +19,7 @@ jobs:
contents: read
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
diff --git a/.gitignore b/.gitignore
index 23c5777f4c..d0bd39a787 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,6 +47,8 @@ design/
frontend/blob-report/
frontend/coverage
frontend/dist
+frontend/.next
+frontend/out
frontend/npm-debug.log*
frontend/playwright-report/
frontend/playwright/.cache/
@@ -61,3 +63,4 @@ venv/
# Snyk Security Extension - AI Rules (auto-generated)
.cursor/rules/snyk_rules.mdc
+semgrep-security-report.txt
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e974cea4a9..ca9565cd55 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -20,7 +20,7 @@ repos:
- --args=--config=__GIT_WORKING_DIR__/infrastructure/.tflint.hcl
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.14.13
+ rev: v0.14.14
hooks:
- id: ruff-check
args:
diff --git a/Makefile b/Makefile
index faba777dac..7f2649e631 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,8 @@ include docs/Makefile
include frontend/Makefile
include infrastructure/Makefile
+.PHONY: build clean check pre-commit prune run scan-images security-scan test update
+
MAKEFLAGS += --no-print-directory
build:
@@ -59,6 +61,44 @@ scan-images: \
scan-backend-image \
scan-frontend-image
+security-scan:
+ @echo "Running Security Scan..."
+ @docker run --rm \
+ -v "$(PWD):/src" \
+ -w /src \
+ $$(grep -E '^FROM semgrep/semgrep:' docker/semgrep/Dockerfile | sed 's/^FROM //') \
+ semgrep \
+ --config p/ci \
+ --config p/command-injection \
+ --config p/cwe-top-25 \
+ --config p/default \
+ --config p/django \
+ --config p/docker \
+ --config p/docker-compose \
+ --config p/dockerfile \
+ --config p/javascript \
+ --config p/nextjs \
+ --config p/nginx \
+ --config p/nodejs \
+ --config p/owasp-top-ten \
+ --config p/python \
+ --config p/r2c-security-audit \
+ --config p/react \
+ --config p/secrets \
+ --config p/secure-defaults \
+ --config p/security-audit \
+ --config p/security-headers \
+ --config p/sql-injection \
+ --config p/terraform \
+ --config p/typescript \
+ --error \
+ --skip-unknown-extensions \
+ --timeout 10 \
+ --timeout-threshold 3 \
+ --text \
+ --text-output=semgrep-security-report.txt \
+ .
+
test: \
test-nest-app
diff --git a/README.md b/README.md
index d0c33c15e2..c17ac89dc1 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
[](https://github.com/OWASP/Nest/issues) [](https://github.com/OWASP/Nest/pulls)
-[](https://www.bestpractices.dev/projects/10174) [](https://snyk.io)
+[](https://www.bestpractices.dev/projects/10174) [](https://snyk.io)
[](https://github.com/OWASP/Nest/network/members) [](https://github.com/OWASP/Nest/stargazers)
diff --git a/backend/apps/api/decorators/cache.py b/backend/apps/api/decorators/cache.py
index 655710cfae..48454e07ea 100644
--- a/backend/apps/api/decorators/cache.py
+++ b/backend/apps/api/decorators/cache.py
@@ -13,7 +13,8 @@ def generate_key(
prefix: str,
):
"""Generate a cache key for a request."""
- return f"{prefix}:{request.get_full_path()}"
+ # Suppress warning as this generates an internal cache key, not a user-facing HTML response.
+ return f"{prefix}:{request.get_full_path()}" # NOSEMGREP: python.flask.security.audit.directly-returned-format-string.directly-returned-format-string # noqa: E501
def cache_response(
diff --git a/backend/apps/api/internal/extensions/__init__.py b/backend/apps/api/internal/extensions/__init__.py
new file mode 100644
index 0000000000..4b350753ac
--- /dev/null
+++ b/backend/apps/api/internal/extensions/__init__.py
@@ -0,0 +1 @@
+"""Strawberry extensions."""
diff --git a/backend/apps/api/internal/extensions/cache.py b/backend/apps/api/internal/extensions/cache.py
new file mode 100644
index 0000000000..1d2396ad12
--- /dev/null
+++ b/backend/apps/api/internal/extensions/cache.py
@@ -0,0 +1,106 @@
+"""Strawberry cache extension."""
+
+import hashlib
+import json
+from functools import lru_cache
+
+from django.conf import settings
+from django.core.cache import cache
+from django.core.serializers.json import DjangoJSONEncoder
+from strawberry.extensions import SchemaExtension
+from strawberry.permission import PermissionExtension
+from strawberry.schema import Schema
+from strawberry.utils.str_converters import to_camel_case
+
+
+@lru_cache(maxsize=1)
+def get_protected_fields(schema: Schema) -> tuple[str, ...]:
+ """Get protected field names.
+
+ Args:
+ schema (Schema): The GraphQL schema.
+
+ Returns:
+ tuple[str, ...]: Tuple of protected field names in camelCase.
+
+ """
+ return tuple(
+ to_camel_case(field.name)
+ for field in getattr(
+ getattr(schema.schema_converter.type_map.get("Query"), "definition", None),
+ "fields",
+ (),
+ )
+ if any(isinstance(ext, PermissionExtension) for ext in field.extensions)
+ )
+
+
+def generate_key(field_name: str, field_args: dict) -> str:
+ """Generate a unique cache key for a query.
+
+ Args:
+ field_name (str): The GraphQL field name.
+ field_args (dict): The field's arguments.
+
+ Returns:
+ str: The unique cache key.
+
+ """
+ key = f"{field_name}:{json.dumps(field_args, cls=DjangoJSONEncoder, sort_keys=True)}"
+ return f"{settings.GRAPHQL_RESOLVER_CACHE_PREFIX}-{hashlib.sha256(key.encode()).hexdigest()}"
+
+
+def invalidate_cache(field_name: str, field_args: dict) -> bool:
+ """Invalidate a specific GraphQL query from the resolver cache.
+
+ Args:
+ field_name: The GraphQL field name (e.g., 'getProgram').
+ field_args: The field's arguments as a dict (e.g., {'programKey': 'my-program'}).
+
+ Returns:
+ True if cache was invalidated, False if key didn't exist.
+
+ """
+ return cache.delete(generate_key(field_name, field_args))
+
+
+def invalidate_program_cache(program_key: str) -> None:
+ """Invalidate all GraphQL caches related to a program.
+
+ Args:
+ program_key: The program's key identifier.
+
+ """
+ invalidate_cache("getProgram", {"programKey": program_key})
+ invalidate_cache("getProgramModules", {"programKey": program_key})
+
+
+def invalidate_module_cache(module_key: str, program_key: str) -> None:
+ """Invalidate all GraphQL caches related to a module.
+
+ Args:
+ module_key: The module's key identifier.
+ program_key: The program's key identifier.
+
+ """
+ invalidate_cache("getModule", {"moduleKey": module_key, "programKey": program_key})
+ invalidate_program_cache(program_key)
+
+
+class CacheExtension(SchemaExtension):
+ """Cache extension."""
+
+ def resolve(self, _next, root, info, *args, **kwargs):
+ """Wrap the resolver to provide caching."""
+ if (
+ info.field_name.startswith("__")
+ or info.parent_type.name != "Query"
+ or info.field_name in get_protected_fields(self.execution_context.schema)
+ ):
+ return _next(root, info, *args, **kwargs)
+
+ return cache.get_or_set(
+ generate_key(info.field_name, kwargs),
+ lambda: _next(root, info, *args, **kwargs),
+ settings.GRAPHQL_RESOLVER_CACHE_TIME_SECONDS,
+ )
diff --git a/backend/apps/api/internal/mutations/api_key.py b/backend/apps/api/internal/mutations/api_key.py
index edbcc49a13..dda381789e 100644
--- a/backend/apps/api/internal/mutations/api_key.py
+++ b/backend/apps/api/internal/mutations/api_key.py
@@ -77,7 +77,10 @@ def create_api_key(self, info: Info, name: str, expires_at: datetime) -> CreateA
message="API key created successfully.",
)
except IntegrityError as err:
- logger.warning("Error creating API key: %s", err)
+ # Logging the error message string only, not the sensitive API key credential itself. # noqa: E501
+ logger.warning( # NOSEMGREP: python.lang.security.audit.logging.logger-credential-leak.python-logger-credential-disclosure # noqa: E501
+ "Error creating API key: %s", err
+ )
return CreateApiKeyResult(
ok=False,
code="ERROR",
diff --git a/backend/apps/common/extensions.py b/backend/apps/common/extensions.py
deleted file mode 100644
index 21e9373950..0000000000
--- a/backend/apps/common/extensions.py
+++ /dev/null
@@ -1,67 +0,0 @@
-"""Strawberry extensions."""
-
-import hashlib
-import json
-from functools import lru_cache
-
-from django.conf import settings
-from django.core.cache import cache
-from strawberry.extensions import SchemaExtension
-from strawberry.permission import PermissionExtension
-from strawberry.schema import Schema
-from strawberry.utils.str_converters import to_camel_case
-
-
-@lru_cache(maxsize=1)
-def get_protected_fields(schema: Schema) -> tuple[str, ...]:
- """Get protected field names.
-
- Args:
- schema (Schema): The GraphQL schema.
-
- Returns:
- tuple[str, ...]: Tuple of protected field names in camelCase.
-
- """
- query_type = schema.schema_converter.type_map.get("Query")
- fields = getattr(getattr(query_type, "definition", None), "fields", ())
- return tuple(
- to_camel_case(field.name)
- for field in fields
- if any(isinstance(ext, PermissionExtension) for ext in field.extensions)
- )
-
-
-class CacheExtension(SchemaExtension):
- """CacheExtension class."""
-
- def generate_key(self, field_name: str, field_args: dict) -> str:
- """Generate a unique cache key for a query.
-
- Args:
- field_name (str): The GraphQL field name.
- field_args (dict): The field's arguments.
-
- Returns:
- str: The unique cache key.
-
- """
- key = f"{field_name}:{json.dumps(field_args, sort_keys=True)}"
- return (
- f"{settings.GRAPHQL_RESOLVER_CACHE_PREFIX}-{hashlib.sha256(key.encode()).hexdigest()}"
- )
-
- def resolve(self, _next, root, info, *args, **kwargs):
- """Wrap the resolver to provide caching."""
- if (
- info.field_name.startswith("__")
- or info.parent_type.name != "Query"
- or info.field_name in get_protected_fields(self.execution_context.schema)
- ):
- return _next(root, info, *args, **kwargs)
-
- return cache.get_or_set(
- self.generate_key(info.field_name, kwargs),
- lambda: _next(root, info, *args, **kwargs),
- settings.GRAPHQL_RESOLVER_CACHE_TIME_SECONDS,
- )
diff --git a/backend/apps/common/management/commands/purge_data.py b/backend/apps/common/management/commands/purge_data.py
index 54f4252aae..2bdacbf2a4 100644
--- a/backend/apps/common/management/commands/purge_data.py
+++ b/backend/apps/common/management/commands/purge_data.py
@@ -3,6 +3,7 @@
from django.apps import apps
from django.core.management.base import BaseCommand
from django.db import connection
+from psycopg2 import sql
class Command(BaseCommand):
@@ -22,5 +23,10 @@ def handle(self, *_args, **options) -> None:
apps.get_app_config(nest_app).get_models(),
key=lambda m: m.__name__,
):
- cursor.execute(f"TRUNCATE TABLE {model._meta.db_table} CASCADE") # NOSONAR
+ # Suppress false positive sqlalchemy warning.
+ cursor.execute( # NOSEMGREP: python.sqlalchemy.security.sqlalchemy-execute-raw-query.sqlalchemy-execute-raw-query # noqa: E501
+ sql.SQL("TRUNCATE TABLE {} CASCADE").format(
+ sql.Identifier(model._meta.db_table)
+ )
+ )
print(f"Purged {nest_app}.{model.__name__}")
diff --git a/backend/apps/common/template_loader.py b/backend/apps/common/template_loader.py
index 5eadd805b2..3b41ad4575 100644
--- a/backend/apps/common/template_loader.py
+++ b/backend/apps/common/template_loader.py
@@ -8,5 +8,10 @@
SLACK_TEMPLATES_DIR = BASE_DIR / "slack" / "templates"
VIDEO_TEMPLATES_DIR = BASE_DIR / "owasp" / "templates" / "video"
-slack_env = Environment(loader=FileSystemLoader(SLACK_TEMPLATES_DIR), autoescape=True)
-video_env = Environment(loader=FileSystemLoader(VIDEO_TEMPLATES_DIR), autoescape=True)
+# Suppress false positive Flask security warning.
+slack_env = Environment( # NOSEMGREP: python.flask.security.xss.audit.direct-use-of-jinja2.direct-use-of-jinja2 # noqa: E501
+ loader=FileSystemLoader(SLACK_TEMPLATES_DIR), autoescape=True
+)
+video_env = Environment( # NOSEMGREP: python.flask.security.xss.audit.direct-use-of-jinja2.direct-use-of-jinja2 # noqa: E501
+ loader=FileSystemLoader(VIDEO_TEMPLATES_DIR), autoescape=True
+)
diff --git a/backend/apps/github/admin/issue.py b/backend/apps/github/admin/issue.py
index 3c397dcd85..17f87e64c8 100644
--- a/backend/apps/github/admin/issue.py
+++ b/backend/apps/github/admin/issue.py
@@ -1,7 +1,7 @@
"""GitHub app Issue model admin."""
from django.contrib import admin
-from django.utils.safestring import mark_safe
+from django.utils.html import format_html
from apps.github.models.issue import Issue
@@ -38,7 +38,7 @@ def custom_field_github_url(self, obj) -> str:
str: A safe HTML link to the issue on GitHub.
"""
- return mark_safe(f"↗️") # noqa: S308
+ return format_html("↗️", obj.url)
custom_field_github_url.short_description = "GitHub 🔗"
diff --git a/backend/apps/github/admin/pull_request.py b/backend/apps/github/admin/pull_request.py
index 02937114b4..f5c5d00f3d 100644
--- a/backend/apps/github/admin/pull_request.py
+++ b/backend/apps/github/admin/pull_request.py
@@ -1,7 +1,7 @@
"""GitHub app PullRequest model admin."""
from django.contrib import admin
-from django.utils.safestring import mark_safe
+from django.utils.html import format_html
from apps.github.models.pull_request import PullRequest
@@ -44,7 +44,7 @@ def custom_field_github_url(self, obj: PullRequest) -> str:
str: A safe HTML link to the pull request on GitHub.
"""
- return mark_safe(f"↗️") # noqa: S308
+ return format_html("↗️", obj.url)
custom_field_github_url.short_description = "GitHub 🔗"
diff --git a/backend/apps/github/admin/repository.py b/backend/apps/github/admin/repository.py
index 66dcdc18aa..ba17eb19ca 100644
--- a/backend/apps/github/admin/repository.py
+++ b/backend/apps/github/admin/repository.py
@@ -1,7 +1,7 @@
"""GitHub app Repository model admin."""
from django.contrib import admin
-from django.utils.safestring import mark_safe
+from django.utils.html import format_html
from apps.github.models.repository import Repository
@@ -46,8 +46,10 @@ def custom_field_github_url(self, obj) -> str:
str: A safe HTML link to the repository on GitHub.
"""
- return mark_safe( # noqa: S308
- f"↗️"
+ return format_html(
+ "↗️",
+ obj.owner.login,
+ obj.name,
)
def custom_field_title(self, obj: Repository) -> str:
diff --git a/backend/apps/github/models/mixins/repository.py b/backend/apps/github/models/mixins/repository.py
index 6bd7b27b6c..5586d1e9c0 100644
--- a/backend/apps/github/models/mixins/repository.py
+++ b/backend/apps/github/models/mixins/repository.py
@@ -14,7 +14,12 @@ class RepositoryIndexMixin:
@property
def is_indexable(self) -> bool:
- """Repositories to index."""
+ """Determine if the repository should be indexed.
+
+ Returns:
+ bool: True if repository meets all indexing criteria, False otherwise.
+
+ """
return (
not self.is_archived
and not self.is_empty
@@ -24,90 +29,182 @@ def is_indexable(self) -> bool:
@property
def idx_commits_count(self) -> int:
- """Return commits count for indexing."""
+ """Get the total number of commits in this repository for indexing.
+
+ Returns:
+ int: The total commit count of the repository.
+
+ """
return self.commits_count
@property
def idx_contributors_count(self) -> int:
- """Return contributors count for indexing."""
+ """Get the total number of contributors to this repository for indexing.
+
+ Returns:
+ int: The total number of unique contributors.
+
+ """
return self.contributors_count
@property
def idx_created_at(self) -> float:
- """Return created at for indexing."""
+ """Get the repository creation timestamp for indexing.
+
+ Returns:
+ float: Unix timestamp when the repository was created.
+
+ """
return self.created_at.timestamp()
@property
def idx_description(self) -> str:
- """Return description for indexing."""
+ """Get the repository description for indexing.
+
+ Returns:
+ str: The repository's description text.
+
+ """
return self.description
@property
def idx_forks_count(self) -> int:
- """Return forks count for indexing."""
+ """Get the total number of repository forks for indexing.
+
+ Returns:
+ int: The total number of times this repository has been forked.
+
+ """
return self.forks_count
@property
def idx_has_funding_yml(self) -> bool:
- """Return has funding.yml for indexing."""
+ """Check if the repository has a FUNDING.yml file for indexing.
+
+ Returns:
+ bool: True if the repository contains a FUNDING.yml file, False otherwise.
+
+ """
return self.has_funding_yml
@property
def idx_key(self) -> str:
- """Return key for indexing."""
+ """Get the unique Nest key identifier for this repository for indexing.
+
+ Returns:
+ str: The repository's unique Nest key.
+
+ """
return self.nest_key
@property
def idx_languages(self) -> list[str]:
- """Return languages for indexing."""
+ """Get the programming languages used in this repository for indexing.
+
+ Returns:
+ list[str]: A list of programming language names detected in the repository.
+
+ """
return self.languages
@property
def idx_license(self) -> str:
- """Return license for indexing."""
+ """Get the repository's license identifier for indexing.
+
+ Returns:
+ str: The license identifier.
+
+ """
return self.license
@property
def idx_name(self) -> str:
- """Return name for indexing."""
+ """Get the repository name for indexing.
+
+ Returns:
+ str: The name of the repository.
+
+ """
return self.name
@property
def idx_open_issues_count(self) -> int:
- """Return open issues count for indexing."""
+ """Get the total number of open issues in this repository for indexing.
+
+ Returns:
+ int: The count of currently open issues.
+
+ """
return self.open_issues_count
@property
def idx_project_key(self) -> str:
- """Return project key for indexing."""
+ """Get the Nest key of the associated project for indexing.
+
+ Returns:
+ str: The unique Nest key of the project this repository belongs to,
+ or an empty string if no project is associated.
+
+ """
return self.project.nest_key if self.project else ""
@property
def idx_pushed_at(self) -> float:
- """Return pushed at for indexing."""
+ """Get the timestamp of the last push to this repository for indexing.
+
+ Returns:
+ float: Unix timestamp of the most recent push.
+
+ """
return self.pushed_at.timestamp()
@property
def idx_size(self) -> int:
- """Return size for indexing."""
+ """Get the repository size in kilobytes for indexing.
+
+ Returns:
+ int: The repository size in KB.
+
+ """
return self.size
@property
def idx_stars_count(self) -> int:
- """Return stars count for indexing."""
+ """Get the total number of stars this repository has received for indexing.
+
+ Returns:
+ int: The total count of stars on the repository.
+
+ """
return self.stars_count
@property
def idx_subscribers_count(self) -> int:
- """Return subscribers count for indexing."""
- return self.stars_count
+ """Get the total number of subscribers for this repository for indexing.
+
+ Returns:
+ int: The count of users watching this repository.
+
+ """
+ return self.subscribers_count
@property
def idx_top_contributors(self) -> list[dict[str, Any]]:
- """Return top contributors for indexing."""
+ """Get the list of top contributors to this repository for indexing.
+
+ Returns:
+ list[dict[str, Any]]: A list of dictionaries containing information about
+ the top contributors to this repository.
+
+ """
return RepositoryContributor.get_top_contributors(repository=self.key)
@property
- def idx_topics(self):
- """Return topics for indexing."""
+ def idx_topics(self) -> list[str]:
+ """Get the topics associated with this repository for indexing.
+
+ Returns:
+ list: A list of topics that categorize this repository.
+
+ """
return self.topics
diff --git a/backend/apps/github/models/mixins/user.py b/backend/apps/github/models/mixins/user.py
index bdbb2c2f19..ed25aedc26 100644
--- a/backend/apps/github/models/mixins/user.py
+++ b/backend/apps/github/models/mixins/user.py
@@ -12,7 +12,12 @@ class UserIndexMixin:
@property
def is_indexable(self):
- """Users to index."""
+ """Determine if the user should be indexed.
+
+ Returns:
+ bool: True if the user meets all indexing criteria, False otherwise.
+
+ """
return (
not self.is_bot
and not self.login.endswith(("Bot", "-bot"))
@@ -21,77 +26,154 @@ def is_indexable(self):
@property
def idx_avatar_url(self) -> str:
- """Return avatar URL for indexing."""
+ """Get the user's avatar URL for indexing.
+
+ Returns:
+ str: The URL of the user's avatar image.
+
+ """
return self.avatar_url
@property
def idx_badge_count(self) -> int:
- """Return badge count for indexing."""
+ """Get the number of active badges associated with the user.
+
+ Returns:
+ int: The count of active user badges.
+
+ """
return self.user_badges.filter(is_active=True).count()
@property
def idx_bio(self) -> str:
- """Return bio for indexing."""
+ """Get the user's biography text for indexing.
+
+ Returns:
+ str: The user's bio, if provided; otherwise an empty string.
+
+ """
return self.bio
@property
def idx_company(self) -> str:
- """Return company for indexing."""
+ """Get the user's company affiliation for indexing.
+
+ Returns:
+ str: The company name associated with the user's profile, if any.
+
+ """
return self.company
@property
def idx_created_at(self) -> float:
- """Return created at timestamp for indexing."""
+ """Get the account creation timestamp for indexing.
+
+ Returns:
+ float: Unix timestamp when the account was created.
+
+ """
return self.created_at.timestamp()
@property
def idx_email(self) -> str:
- """Return email for indexing."""
+ """Get the user's email address for indexing.
+
+ Returns:
+ str: The user's email address, if available.
+
+ """
return self.email
@property
def idx_key(self) -> str:
- """Return key for indexing."""
+ """Get the unique key identifier for this user used in indexing.
+
+ Returns:
+ str: The user's login, used as the unique key.
+
+ """
return self.login
@property
def idx_followers_count(self) -> int:
- """Return followers count for indexing."""
+ """Get the number of followers for the user.
+
+ Returns:
+ int: Total count of users following this user.
+
+ """
return self.followers_count
@property
def idx_following_count(self) -> int:
- """Return following count for indexing."""
+ """Get the number of users the user is following.
+
+ Returns:
+ int: Total count of users this user follows.
+
+ """
return self.following_count
@property
def idx_location(self) -> str:
- """Return location for indexing."""
+ """Get the user's location for indexing.
+
+ Returns:
+ str: The user's self-declared location, if available.
+
+ """
return self.location
@property
def idx_login(self) -> str:
- """Return login for indexing."""
+ """Get the user's login for indexing.
+
+ Returns:
+ str: The user's GitHub login handle.
+
+ """
return self.login
@property
def idx_name(self) -> str:
- """Return name for indexing."""
+ """Get the user's display name for indexing.
+
+ Returns:
+ str: The full name displayed on the user's profile, if provided.
+
+ """
return self.name
@property
def idx_public_repositories_count(self) -> int:
- """Return public repositories count for indexing."""
+ """Get the number of public repositories owned by the user.
+
+ Returns:
+ int: Total count of public repositories owned by the user.
+
+ """
return self.public_repositories_count
@property
def idx_title(self) -> str:
- """Return title for indexing."""
+ """Get the user's profile title or headline for indexing.
+
+ Returns:
+ str: The title or headline associated with the user.
+
+ """
return self.title
@property
def idx_contributions(self):
- """Return contributions for indexing."""
+ """Get a summary of the user's top repository contributions for indexing.
+
+ Returns:
+ list[dict]: A list of contribution summaries, each including counts and
+ metadata about the contributed repositories (e.g., name, stars,
+ forks, license, and latest release information).
+
+ """
from apps.github.models.repository_contributor import RepositoryContributor
return [
@@ -123,12 +205,23 @@ def idx_contributions(self):
@property
def idx_contributions_count(self) -> int:
- """Return contributions count for indexing."""
+ """Get the total number of contributions made by the user.
+
+ Returns:
+ int: Aggregate contributions count across repositories.
+
+ """
return self.contributions_count
@property
def idx_issues(self) -> list[dict]:
- """Return issues for indexing."""
+ """Get recent issues associated with the user for indexing.
+
+ Returns:
+ list[dict]: A list of issue summaries including timestamps, counts,
+ identifiers, titles, URLs, and minimal repository metadata.
+
+ """
return [
{
"created_at": i.created_at.timestamp(),
@@ -149,12 +242,24 @@ def idx_issues(self) -> list[dict]:
@property
def idx_issues_count(self) -> int:
- """Return issues count for indexing."""
+ """Get the total number of issues associated with the user.
+
+ Returns:
+ int: Count of issues linked to the user.
+
+ """
return self.issues.count()
@property
def idx_releases(self) -> list[dict]:
- """Return releases for indexing."""
+ """Get releases associated with the user for indexing.
+
+ Returns:
+ list[dict]: A list of release summaries including pre-release flag,
+ names, published timestamps, tags, URLs, and minimal repository
+ metadata.
+
+ """
return [
{
"is_pre_release": r.is_pre_release,
@@ -175,15 +280,30 @@ def idx_releases(self) -> list[dict]:
@property
def idx_releases_count(self) -> int:
- """Return releases count for indexing."""
+ """Get the total number of releases associated with the user.
+
+ Returns:
+ int: Count of releases linked to the user.
+
+ """
return self.releases.count()
@property
def idx_updated_at(self) -> float:
- """Return updated at timestamp for indexing."""
+ """Get the last profile update timestamp for indexing.
+
+ Returns:
+ float: Unix timestamp (seconds since epoch) of the last update.
+
+ """
return self.updated_at.timestamp()
@property
def idx_url(self) -> str:
- """Return GitHub profile URL for indexing."""
+ """Get the user's GitHub profile URL for indexing.
+
+ Returns:
+ str: The URL to the user's GitHub profile page.
+
+ """
return self.url
diff --git a/backend/apps/mentorship/api/internal/mutations/module.py b/backend/apps/mentorship/api/internal/mutations/module.py
index 96e95c3dd4..5244ee69cf 100644
--- a/backend/apps/mentorship/api/internal/mutations/module.py
+++ b/backend/apps/mentorship/api/internal/mutations/module.py
@@ -8,6 +8,7 @@
from django.db import transaction
from django.utils import timezone
+from apps.api.internal.extensions.cache import invalidate_module_cache, invalidate_program_cache
from apps.github.models import User as GithubUser
from apps.mentorship.api.internal.nodes.module import (
CreateModuleInput,
@@ -20,6 +21,7 @@
from apps.nest.api.internal.permissions import IsAuthenticated
from apps.owasp.models import Project
+ASSIGNEE_NOT_FOUND_MSG = "Assignee not found."
ISSUE_NOT_FOUND_MSG = "Issue not found in this module."
MODULE_NOT_FOUND_MSG = "Module not found."
@@ -38,6 +40,7 @@ def resolve_mentors_from_logins(logins: list[str]) -> set[Mentor]:
msg = f"GitHub user '{login}' not found."
logger.warning(msg, exc_info=True)
raise ValueError(msg) from e
+
return mentors
@@ -119,6 +122,8 @@ def create_module(self, info: strawberry.Info, input_data: CreateModuleInput) ->
mentors_to_set.add(creator_as_mentor)
module.mentors.set(list(mentors_to_set))
+ transaction.on_commit(lambda: invalidate_program_cache(program.key))
+
return module
@strawberry.mutation(permission_classes=[IsAuthenticated])
@@ -141,7 +146,7 @@ def assign_issue_to_user(
.first()
)
if module is None:
- raise ObjectDoesNotExist(msg=MODULE_NOT_FOUND_MSG)
+ raise ObjectDoesNotExist(MODULE_NOT_FOUND_MSG)
mentor = Mentor.objects.filter(nest_user=user).first()
if mentor is None:
@@ -151,11 +156,11 @@ def assign_issue_to_user(
gh_user = GithubUser.objects.filter(login=user_login).first()
if gh_user is None:
- raise ObjectDoesNotExist(msg="Assignee not found.")
+ raise ObjectDoesNotExist(ASSIGNEE_NOT_FOUND_MSG)
issue = module.issues.filter(number=issue_number).first()
if issue is None:
- raise ObjectDoesNotExist(msg=ISSUE_NOT_FOUND_MSG)
+ raise ObjectDoesNotExist(ISSUE_NOT_FOUND_MSG)
issue.assignees.add(gh_user)
@@ -183,7 +188,7 @@ def unassign_issue_from_user(
.first()
)
if module is None:
- raise ObjectDoesNotExist(msg=MODULE_NOT_FOUND_MSG)
+ raise ObjectDoesNotExist(MODULE_NOT_FOUND_MSG)
mentor = Mentor.objects.filter(nest_user=user).first()
if mentor is None:
@@ -193,11 +198,12 @@ def unassign_issue_from_user(
gh_user = GithubUser.objects.filter(login=user_login).first()
if gh_user is None:
- raise ObjectDoesNotExist(msg="Assignee not found.")
+ raise ObjectDoesNotExist(ASSIGNEE_NOT_FOUND_MSG)
issue = module.issues.filter(number=issue_number).first()
if issue is None:
- raise ObjectDoesNotExist(msg=f"Issue {issue_number} not found in this module.")
+ msg = f"Issue {issue_number} not found in this module."
+ raise ObjectDoesNotExist(msg)
issue.assignees.remove(gh_user)
@@ -223,7 +229,7 @@ def set_task_deadline(
.first()
)
if module is None:
- raise ObjectDoesNotExist(msg=MODULE_NOT_FOUND_MSG)
+ raise ObjectDoesNotExist(MODULE_NOT_FOUND_MSG)
mentor = Mentor.objects.filter(nest_user=user).first()
if mentor is None:
@@ -238,7 +244,7 @@ def set_task_deadline(
.first()
)
if issue is None:
- raise ObjectDoesNotExist(msg=ISSUE_NOT_FOUND_MSG)
+ raise ObjectDoesNotExist(ISSUE_NOT_FOUND_MSG)
assignees = issue.assignees.all()
if not assignees.exists():
@@ -285,7 +291,7 @@ def clear_task_deadline(
.first()
)
if module is None:
- raise ObjectDoesNotExist(msg=MODULE_NOT_FOUND_MSG)
+ raise ObjectDoesNotExist(MODULE_NOT_FOUND_MSG)
mentor = Mentor.objects.filter(nest_user=user).first()
if mentor is None:
@@ -300,7 +306,7 @@ def clear_task_deadline(
.first()
)
if issue is None:
- raise ObjectDoesNotExist(msg=ISSUE_NOT_FOUND_MSG)
+ raise ObjectDoesNotExist(ISSUE_NOT_FOUND_MSG)
assignees = issue.assignees.all()
if not assignees.exists():
@@ -330,8 +336,9 @@ def update_module(self, info: strawberry.Info, input_data: UpdateModuleInput) ->
module = Module.objects.select_related("program").get(
key=input_data.key, program__key=input_data.program_key
)
+ old_module_key = module.key
except Module.DoesNotExist as e:
- raise ObjectDoesNotExist(msg=MODULE_NOT_FOUND_MSG) from e
+ raise ObjectDoesNotExist(MODULE_NOT_FOUND_MSG) from e
try:
creator_as_mentor = Mentor.objects.get(nest_user=user)
@@ -400,4 +407,13 @@ def update_module(self, info: strawberry.Info, input_data: UpdateModuleInput) ->
module.program.save(update_fields=["experience_levels"])
+ program_key = module.program.key
+
+ def _invalidate():
+ invalidate_module_cache(old_module_key, program_key)
+ if module.key != old_module_key:
+ invalidate_module_cache(module.key, program_key)
+
+ transaction.on_commit(_invalidate)
+
return module
diff --git a/backend/apps/mentorship/api/internal/mutations/program.py b/backend/apps/mentorship/api/internal/mutations/program.py
index 0905e28c53..88bba96ad8 100644
--- a/backend/apps/mentorship/api/internal/mutations/program.py
+++ b/backend/apps/mentorship/api/internal/mutations/program.py
@@ -6,6 +6,7 @@
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError
from django.db import transaction
+from apps.api.internal.extensions.cache import invalidate_program_cache
from apps.mentorship.api.internal.mutations.module import resolve_mentors_from_logins
from apps.mentorship.api.internal.nodes.enum import ProgramStatusEnum
from apps.mentorship.api.internal.nodes.program import (
@@ -76,6 +77,7 @@ def update_program(self, info: strawberry.Info, input_data: UpdateProgramInput)
try:
program = Program.objects.get(key=input_data.key)
+ old_key = program.key
except Program.DoesNotExist as err:
msg = f"Program with key '{input_data.key}' not found."
logger.warning(msg, exc_info=True)
@@ -133,6 +135,13 @@ def update_program(self, info: strawberry.Info, input_data: UpdateProgramInput)
admins_to_set = resolve_mentors_from_logins(input_data.admin_logins)
program.admins.set(admins_to_set)
+ def _invalidate():
+ invalidate_program_cache(old_key)
+ if program.key != old_key:
+ invalidate_program_cache(program.key)
+
+ transaction.on_commit(_invalidate)
+
return program
@strawberry.mutation(permission_classes=[IsAuthenticated])
@@ -161,6 +170,8 @@ def update_program_status(
program.status = input_data.status.value
program.save()
+ transaction.on_commit(lambda: invalidate_program_cache(program.key))
+
logger.info("Updated status of program '%s' to '%s'", program.key, program.status)
return program
diff --git a/backend/apps/mentorship/api/internal/nodes/module.py b/backend/apps/mentorship/api/internal/nodes/module.py
index 8ccbdf46f1..0a224089d3 100644
--- a/backend/apps/mentorship/api/internal/nodes/module.py
+++ b/backend/apps/mentorship/api/internal/nodes/module.py
@@ -5,8 +5,10 @@
import strawberry
from apps.github.api.internal.nodes.issue import IssueNode
+from apps.github.api.internal.nodes.pull_request import PullRequestNode
from apps.github.api.internal.nodes.user import UserNode
from apps.github.models import Label
+from apps.github.models.pull_request import PullRequest
from apps.github.models.user import User
from apps.mentorship.api.internal.nodes.enum import ExperienceLevelEnum
from apps.mentorship.api.internal.nodes.mentor import MentorNode
@@ -158,6 +160,17 @@ def task_assigned_at(self, issue_number: int) -> datetime | None:
.first()
)
+ @strawberry.field
+ def recent_pull_requests(self, limit: int = 5) -> list[PullRequestNode]:
+ """Return recent pull requests linked to issues in this module."""
+ issue_ids = self.issues.values_list("id", flat=True)
+ return list(
+ PullRequest.objects.filter(related_issues__id__in=issue_ids)
+ .select_related("author")
+ .distinct()
+ .order_by("-created_at")[:limit]
+ )
+
@strawberry.input
class CreateModuleInput:
diff --git a/backend/apps/mentorship/api/internal/nodes/program.py b/backend/apps/mentorship/api/internal/nodes/program.py
index 463caa076f..bee27227ec 100644
--- a/backend/apps/mentorship/api/internal/nodes/program.py
+++ b/backend/apps/mentorship/api/internal/nodes/program.py
@@ -4,6 +4,8 @@
import strawberry
+from apps.github.api.internal.nodes.milestone import MilestoneNode # noqa: TC001
+from apps.github.models.milestone import Milestone
from apps.mentorship.api.internal.nodes.enum import (
ExperienceLevelEnum,
ProgramStatusEnum,
@@ -33,6 +35,19 @@ def admins(self) -> list[MentorNode] | None:
"""Get the list of program administrators."""
return self.admins.all()
+ @strawberry.field
+ def recent_milestones(self) -> list["MilestoneNode"]:
+ """Get the list of recent milestones for the program."""
+ project_ids = self.modules.values_list("project_id", flat=True)
+
+ return (
+ Milestone.open_milestones.filter(repository__project__in=project_ids)
+ .select_related("repository__organization", "author")
+ .prefetch_related("labels")
+ .order_by("-created_at")
+ .distinct()
+ )
+
@strawberry.type
class PaginatedPrograms:
diff --git a/backend/apps/mentorship/signals/__init__.py b/backend/apps/mentorship/signals/__init__.py
index 376a8c1d0e..00b53d5574 100644
--- a/backend/apps/mentorship/signals/__init__.py
+++ b/backend/apps/mentorship/signals/__init__.py
@@ -1 +1 @@
-from .program import ProgramPostSaveHandler
+from .program import program_post_save_clear_algolia_cache
diff --git a/backend/apps/mentorship/signals/program.py b/backend/apps/mentorship/signals/program.py
index 6e8200197a..66b5f3462a 100644
--- a/backend/apps/mentorship/signals/program.py
+++ b/backend/apps/mentorship/signals/program.py
@@ -11,14 +11,8 @@
logger = logging.getLogger(__name__)
-class ProgramPostSaveHandler:
- """Handles post_save signal for Program model to clear Algolia cache."""
-
- @receiver(post_save, sender=Program)
- def program_post_save_clear_algolia_cache(sender, instance, **kwargs): # noqa: N805
- """Signal handler to clear Algolia cache for the Program index.
-
- The sender, instance, and kwargs arguments are provided by the post_save signal.
- """
- logger.info("Signal received for program '%s'. Clearing 'programs' index.", instance.name)
- clear_index_cache("programs")
+@receiver(post_save, sender=Program)
+def program_post_save_clear_algolia_cache(sender, instance, **kwargs): # noqa: ARG001
+ """Signal handler to clear Algolia cache for the Program index."""
+ logger.info("Signal received for program '%s'. Clearing 'programs' index.", instance.name)
+ clear_index_cache("programs")
diff --git a/backend/apps/owasp/admin/mixins.py b/backend/apps/owasp/admin/mixins.py
index 9addfc4a6e..59b7839484 100644
--- a/backend/apps/owasp/admin/mixins.py
+++ b/backend/apps/owasp/admin/mixins.py
@@ -2,7 +2,7 @@
from django.contrib.contenttypes.admin import GenericTabularInline
from django.contrib.contenttypes.models import ContentType
-from django.utils.html import escape
+from django.utils.html import format_html
from django.utils.safestring import mark_safe
from apps.owasp.admin.widgets import ChannelIdWidget
@@ -106,10 +106,10 @@ def custom_field_github_urls(self, obj):
return ""
return self._format_github_link(obj.owasp_repository)
- return mark_safe( # noqa: S308
- " ".join(
- [self._format_github_link(repository) for repository in obj.repositories.all()]
- )
+ links = [self._format_github_link(repository) for repository in obj.repositories.all()]
+ # Use mark_safe since links are already safely formatted HTML from format_html
+ return mark_safe( # noqa: S308 # NOSEMGREP: python.django.security.audit.avoid-mark-safe.avoid-mark-safe
+ " ".join(links)
)
def custom_field_owasp_url(self, obj):
@@ -117,9 +117,7 @@ def custom_field_owasp_url(self, obj):
if not hasattr(obj, "key") or not obj.key:
return ""
- return mark_safe( # noqa: S308
- f"↗️"
- )
+ return format_html("↗️", obj.key)
def _format_github_link(self, repository):
"""Format a single GitHub repository link."""
@@ -130,9 +128,10 @@ def _format_github_link(self, repository):
if not hasattr(repository, "key") or not repository.key:
return ""
- return mark_safe( # noqa: S308
- f"↗️"
+ return format_html(
+ "↗️",
+ repository.owner.login,
+ repository.key,
)
custom_field_github_urls.short_description = "GitHub 🔗"
diff --git a/backend/apps/owasp/admin/widgets.py b/backend/apps/owasp/admin/widgets.py
index 7765ade609..409fdee692 100644
--- a/backend/apps/owasp/admin/widgets.py
+++ b/backend/apps/owasp/admin/widgets.py
@@ -21,4 +21,7 @@ def render(self, name, value, attrs=None, renderer=None):
f"id='lookup_id_{name}' title='Look up related objects'>"
)
- return mark_safe(f"{widget_html}{search_button}") # noqa: S308
+ # Use mark_safe since both widget_html and search_button are already HTML
+ return mark_safe( # noqa: S308 # NOSEMGREP: python.django.security.audit.avoid-mark-safe.avoid-mark-safe
+ f"{widget_html} {search_button}"
+ )
diff --git a/backend/apps/owasp/models/project.py b/backend/apps/owasp/models/project.py
index 0a6ecdcafb..37305845b7 100644
--- a/backend/apps/owasp/models/project.py
+++ b/backend/apps/owasp/models/project.py
@@ -159,44 +159,84 @@ def __str__(self) -> str:
@property
def entity_leaders(self) -> list[EntityMember]:
- """Return project leaders."""
+ """Get the list of project leaders.
+
+ Returns:
+ list[EntityMember]: Up to the top leaders limited by `MAX_LEADERS_COUNT`.
+
+ """
return super().entity_leaders[:MAX_LEADERS_COUNT]
@property
def health_score(self) -> float | None:
- """Return project health score."""
+ """Get the latest computed health score for the project.
+
+ Returns:
+ float | None: The most recent health score, or None if unavailable.
+
+ """
return self.last_health_metrics.score if self.last_health_metrics else None
@property
def is_code_type(self) -> bool:
- """Indicate whether project has CODE type."""
+ """Check if the project's type is CODE.
+
+ Returns:
+ bool: True if the project type equals `ProjectType.CODE`.
+
+ """
return self.type == ProjectType.CODE
@property
def is_documentation_type(self) -> bool:
- """Indicate whether project has DOCUMENTATION type."""
+ """Check if the project's type is DOCUMENTATION.
+
+ Returns:
+ bool: True if the project type equals `ProjectType.DOCUMENTATION`.
+
+ """
return self.type == ProjectType.DOCUMENTATION
@property
def is_funding_requirements_compliant(self) -> bool:
- """Indicate whether project is compliant with funding requirements."""
+ """Check if the project complies with funding requirements.
+
+ Returns:
+ bool: True if all related repositories are funding-policy compliant.
+
+ """
return not self.repositories.filter(is_funding_policy_compliant=False).exists()
@property
def is_leader_requirements_compliant(self) -> bool:
- """Indicate whether project is compliant with project leaders requirements."""
+ """Check if the project satisfies OWASP leader requirements.
+
+ Returns:
+ bool: True if the project has multiple leaders (more than one).
+
+ """
# https://owasp.org/www-committee-project/#div-practice
# Have multiple Project Leaders who are not all employed by the same company.
return self.leaders_count > 1
@property
def is_tool_type(self) -> bool:
- """Indicate whether project has TOOL type."""
+ """Check if the project's type is TOOL.
+
+ Returns:
+ bool: True if the project type equals `ProjectType.TOOL`.
+
+ """
return self.type == ProjectType.TOOL
@property
def issues(self):
- """Return issues."""
+ """Get issues across the project's repositories.
+
+ Returns:
+ QuerySet[Issue]: A queryset of issues with related entities prefetched.
+
+ """
return (
Issue.objects.filter(
repository__in=self.repositories.all(),
@@ -215,32 +255,62 @@ def issues(self):
@property
def issues_count(self) -> int:
- """Return count of issues."""
+ """Get the total number of issues.
+
+ Returns:
+ int: Count of issues across the project's repositories.
+
+ """
return self.issues.count()
@property
def last_health_metrics(self) -> ProjectHealthMetrics | None:
- """Return last health metrics for the project."""
+ """Get the most recent health metrics for the project.
+
+ Returns:
+ ProjectHealthMetrics | None: Latest metrics record or None if missing.
+
+ """
return self.health_metrics.order_by("-nest_created_at").first()
@property
def leaders_count(self) -> int:
- """Return the count of leaders."""
+ """Get the number of project leaders.
+
+ Returns:
+ int: Count of leaders derived from `leaders_raw`.
+
+ """
return len(self.leaders_raw)
@property
def nest_key(self) -> str:
- """Get Nest key."""
+ """Get the Nest-specific project key.
+
+ Returns:
+ str: The project key with the "www-project-" prefix removed.
+
+ """
return self.key.replace("www-project-", "")
@property
def nest_url(self) -> str:
- """Get Nest URL for project."""
+ """Get the absolute Nest URL for this project.
+
+ Returns:
+ str: The full Nest URL pointing to the project's page.
+
+ """
return get_absolute_url(f"/projects/{self.nest_key}")
@property
def open_issues(self):
- """Return open issues."""
+ """Get open issues across the project's repositories.
+
+ Returns:
+ QuerySet[Issue]: A queryset of open issues with repository related data.
+
+ """
return Issue.open_issues.filter(
repository__in=self.repositories.all(),
).select_related(
@@ -249,17 +319,32 @@ def open_issues(self):
@property
def open_pull_requests_count(self) -> int:
- """Return count of open pull requests."""
+ """Get the number of open pull requests.
+
+ Returns:
+ int: Count of pull requests currently in the "open" state.
+
+ """
return self.pull_requests.filter(state="open").count()
@property
def owasp_page_last_updated_at(self) -> datetime.datetime | None:
- """Return the last updated date of the OWASP page."""
+ """Get the last updated timestamp of the project's OWASP page.
+
+ Returns:
+ datetime.datetime | None: The OWASP page's last update time, or None.
+
+ """
return self.owasp_repository.updated_at if self.owasp_repository else None
@property
def pull_requests(self):
- """Return pull requests."""
+ """Get pull requests across the project's repositories.
+
+ Returns:
+ QuerySet[PullRequest]: A queryset of pull requests with related data.
+
+ """
return (
PullRequest.objects.filter(
repository__in=self.repositories.all(),
@@ -278,19 +363,34 @@ def pull_requests(self):
@property
def pull_requests_count(self) -> int:
- """Return count of pull requests."""
+ """Get the total number of pull requests.
+
+ Returns:
+ int: Count of pull requests across the project's repositories.
+
+ """
return self.pull_requests.count()
@property
def pull_request_last_created_at(self) -> datetime.datetime | None:
- """Return last created pull request."""
+ """Get the most recent pull request creation timestamp.
+
+ Returns:
+ datetime.datetime | None: Latest `created_at` timestamp, or None.
+
+ """
return self.pull_requests.aggregate(
models.Max("created_at"),
)["created_at__max"]
@property
- def published_releases(self):
- """Return project releases."""
+ def published_releases(self) -> models.QuerySet[Release]:
+ """Get published releases across the project's repositories.
+
+ Returns:
+ QuerySet[Release]: A queryset of non-draft releases with related data.
+
+ """
return Release.objects.filter(
is_draft=False,
published_at__isnull=False,
@@ -302,8 +402,13 @@ def published_releases(self):
)
@property
- def recent_milestones(self):
- """Return recent milestones."""
+ def recent_milestones(self) -> models.QuerySet[Milestone]:
+ """Get milestones across the project's repositories.
+
+ Returns:
+ QuerySet[Milestone]: A queryset of milestones with related data.
+
+ """
return (
Milestone.objects.filter(
repository__in=self.repositories.all(),
@@ -319,7 +424,12 @@ def recent_milestones(self):
@property
def recent_releases_count(self) -> int:
- """Return count of recent releases per a specific period."""
+ """Get the number of recent releases.
+
+ Returns:
+ int: Count of releases published recently.
+
+ """
recent_period = timezone.now() - datetime.timedelta(days=60)
return self.published_releases.filter(
published_at__gte=recent_period,
@@ -327,17 +437,32 @@ def recent_releases_count(self) -> int:
@property
def repositories_count(self) -> int:
- """Return count of repositories."""
+ """Get the number of repositories associated with this project.
+
+ Returns:
+ int: Count of repositories linked to the project.
+
+ """
return self.repositories.count()
@property
def unanswered_issues_count(self) -> int:
- """Return count of unanswered issues."""
+ """Get the number of issues with no comments.
+
+ Returns:
+ int: Count of issues where `comments_count` equals zero.
+
+ """
return self.issues.filter(comments_count=0).count()
@property
def unassigned_issues_count(self) -> int:
- """Return count of unassigned issues."""
+ """Get the number of issues with no assignees.
+
+ Returns:
+ int: Count of issues where no user is assigned.
+
+ """
return self.issues.filter(assignees__isnull=True).count()
def deactivate(self) -> None:
diff --git a/backend/apps/slack/views.py b/backend/apps/slack/views.py
index a3983bf11c..229479e23b 100644
--- a/backend/apps/slack/views.py
+++ b/backend/apps/slack/views.py
@@ -9,7 +9,7 @@
slack_handler = SlackRequestHandler(SlackConfig.app)
-@csrf_exempt # NOSONAR
+@csrf_exempt # NOSEMGREP: python.django.security.audit.csrf-exempt.no-csrf-exempt # NOSONAR
@require_POST # NOSONAR
def slack_request_handler(request):
"""Handle Slack requests.
@@ -20,5 +20,10 @@ def slack_request_handler(request):
Returns:
HttpResponse: The response generated by the SlackRequestHandler.
+ Note:
+ CSRF exemption is required for webhook endpoints. Security is ensured through
+ Slack's request signature verification, which is automatically handled by
+ slack-bolt's SlackRequestHandler when signing_secret is configured in SlackConfig.app.
+
"""
return slack_handler.handle(request)
diff --git a/backend/poetry.lock b/backend/poetry.lock
index 6b3b6411d9..1d6aae8ac5 100644
--- a/backend/poetry.lock
+++ b/backend/poetry.lock
@@ -171,14 +171,14 @@ frozenlist = ">=1.1.0"
[[package]]
name = "algoliasearch"
-version = "4.35.3"
+version = "4.35.4"
description = "A fully-featured and blazing-fast Python API client to interact with Algolia."
optional = false
python-versions = ">=3.8.1"
groups = ["main"]
files = [
- {file = "algoliasearch-4.35.3-py3-none-any.whl", hash = "sha256:5cfd74be60f4844677e5a95737b04044f05815f744447c5ec0eec9459c064c45"},
- {file = "algoliasearch-4.35.3.tar.gz", hash = "sha256:14ece549317cb6ca6c435cc1324c2ab4f5425598bc1b35fa48b1d1d01a0ca39c"},
+ {file = "algoliasearch-4.35.4-py3-none-any.whl", hash = "sha256:4a61efd953357ebc2fd8687bcb8e470a3947f7988367384457ab793172456eda"},
+ {file = "algoliasearch-4.35.4.tar.gz", hash = "sha256:7d958459fa2ec80aa610a425737edec7e6a4d2f704649952b8edd63e4bff44ca"},
]
[package.dependencies]
@@ -306,18 +306,18 @@ wrapt = "*"
[[package]]
name = "boto3"
-version = "1.42.30"
+version = "1.42.34"
description = "The AWS SDK for Python"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "boto3-1.42.30-py3-none-any.whl", hash = "sha256:d7e548bea65e0ae2c465c77de937bc686b591aee6a352d5a19a16bc751e591c1"},
- {file = "boto3-1.42.30.tar.gz", hash = "sha256:ba9cd2f7819637d15bfbeb63af4c567fcc8a7dcd7b93dd12734ec58601169538"},
+ {file = "boto3-1.42.34-py3-none-any.whl", hash = "sha256:db3fb539e3f806b911ec4ca991f2f8bff333c5f0b87132a82e28b521fc5ec164"},
+ {file = "boto3-1.42.34.tar.gz", hash = "sha256:75d7443c81a029283442fad138629be1eefaa3e6d430c28118a0f4cdbd57855d"},
]
[package.dependencies]
-botocore = ">=1.42.30,<1.43.0"
+botocore = ">=1.42.34,<1.43.0"
jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.16.0,<0.17.0"
@@ -326,14 +326,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "botocore"
-version = "1.42.30"
+version = "1.42.34"
description = "Low-level, data-driven core of boto 3."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "botocore-1.42.30-py3-none-any.whl", hash = "sha256:97070a438cac92430bb7b65f8ebd7075224f4a289719da4ee293d22d1e98db02"},
- {file = "botocore-1.42.30.tar.gz", hash = "sha256:9bf1662b8273d5cc3828a49f71ca85abf4e021011c1f0a71f41a2ea5769a5116"},
+ {file = "botocore-1.42.34-py3-none-any.whl", hash = "sha256:94099b5d09d0c4bfa6414fb3cffd54275ce6e51d7ba016f17a0e79f9274f68f7"},
+ {file = "botocore-1.42.34.tar.gz", hash = "sha256:92e44747da7890270d8dcc494ecc61fc315438440c55e00dc37a57d402b1bb66"},
]
[package.dependencies]
@@ -771,104 +771,104 @@ markers = {main = "platform_system == \"Windows\"", test = "sys_platform == \"wi
[[package]]
name = "coverage"
-version = "7.13.1"
+version = "7.13.2"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.10"
groups = ["test"]
files = [
- {file = "coverage-7.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e1fa280b3ad78eea5be86f94f461c04943d942697e0dac889fa18fff8f5f9147"},
- {file = "coverage-7.13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c3d8c679607220979434f494b139dfb00131ebf70bb406553d69c1ff01a5c33d"},
- {file = "coverage-7.13.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:339dc63b3eba969067b00f41f15ad161bf2946613156fb131266d8debc8e44d0"},
- {file = "coverage-7.13.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:db622b999ffe49cb891f2fff3b340cdc2f9797d01a0a202a0973ba2562501d90"},
- {file = "coverage-7.13.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1443ba9acbb593fa7c1c29e011d7c9761545fe35e7652e85ce7f51a16f7e08d"},
- {file = "coverage-7.13.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c832ec92c4499ac463186af72f9ed4d8daec15499b16f0a879b0d1c8e5cf4a3b"},
- {file = "coverage-7.13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:562ec27dfa3f311e0db1ba243ec6e5f6ab96b1edfcfc6cf86f28038bc4961ce6"},
- {file = "coverage-7.13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4de84e71173d4dada2897e5a0e1b7877e5eefbfe0d6a44edee6ce31d9b8ec09e"},
- {file = "coverage-7.13.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:a5a68357f686f8c4d527a2dc04f52e669c2fc1cbde38f6f7eb6a0e58cbd17cae"},
- {file = "coverage-7.13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:77cc258aeb29a3417062758975521eae60af6f79e930d6993555eeac6a8eac29"},
- {file = "coverage-7.13.1-cp310-cp310-win32.whl", hash = "sha256:bb4f8c3c9a9f34423dba193f241f617b08ffc63e27f67159f60ae6baf2dcfe0f"},
- {file = "coverage-7.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:c8e2706ceb622bc63bac98ebb10ef5da80ed70fbd8a7999a5076de3afaef0fb1"},
- {file = "coverage-7.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a55d509a1dc5a5b708b5dad3b5334e07a16ad4c2185e27b40e4dba796ab7f88"},
- {file = "coverage-7.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d010d080c4888371033baab27e47c9df7d6fb28d0b7b7adf85a4a49be9298b3"},
- {file = "coverage-7.13.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d938b4a840fb1523b9dfbbb454f652967f18e197569c32266d4d13f37244c3d9"},
- {file = "coverage-7.13.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bf100a3288f9bb7f919b87eb84f87101e197535b9bd0e2c2b5b3179633324fee"},
- {file = "coverage-7.13.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef6688db9bf91ba111ae734ba6ef1a063304a881749726e0d3575f5c10a9facf"},
- {file = "coverage-7.13.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0b609fc9cdbd1f02e51f67f51e5aee60a841ef58a68d00d5ee2c0faf357481a3"},
- {file = "coverage-7.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c43257717611ff5e9a1d79dce8e47566235ebda63328718d9b65dd640bc832ef"},
- {file = "coverage-7.13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e09fbecc007f7b6afdfb3b07ce5bd9f8494b6856dd4f577d26c66c391b829851"},
- {file = "coverage-7.13.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:a03a4f3a19a189919c7055098790285cc5c5b0b3976f8d227aea39dbf9f8bfdb"},
- {file = "coverage-7.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3820778ea1387c2b6a818caec01c63adc5b3750211af6447e8dcfb9b6f08dbba"},
- {file = "coverage-7.13.1-cp311-cp311-win32.whl", hash = "sha256:ff10896fa55167371960c5908150b434b71c876dfab97b69478f22c8b445ea19"},
- {file = "coverage-7.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:a998cc0aeeea4c6d5622a3754da5a493055d2d95186bad877b0a34ea6e6dbe0a"},
- {file = "coverage-7.13.1-cp311-cp311-win_arm64.whl", hash = "sha256:fea07c1a39a22614acb762e3fbbb4011f65eedafcb2948feeef641ac78b4ee5c"},
- {file = "coverage-7.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6f34591000f06e62085b1865c9bc5f7858df748834662a51edadfd2c3bfe0dd3"},
- {file = "coverage-7.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b67e47c5595b9224599016e333f5ec25392597a89d5744658f837d204e16c63e"},
- {file = "coverage-7.13.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e7b8bd70c48ffb28461ebe092c2345536fb18bbbf19d287c8913699735f505c"},
- {file = "coverage-7.13.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c223d078112e90dc0e5c4e35b98b9584164bea9fbbd221c0b21c5241f6d51b62"},
- {file = "coverage-7.13.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:794f7c05af0763b1bbd1b9e6eff0e52ad068be3b12cd96c87de037b01390c968"},
- {file = "coverage-7.13.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0642eae483cc8c2902e4af7298bf886d605e80f26382124cddc3967c2a3df09e"},
- {file = "coverage-7.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f5e772ed5fef25b3de9f2008fe67b92d46831bd2bc5bdc5dd6bfd06b83b316f"},
- {file = "coverage-7.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:45980ea19277dc0a579e432aef6a504fe098ef3a9032ead15e446eb0f1191aee"},
- {file = "coverage-7.13.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f18eca6028ffa62adbd185a8f1e1dd242f2e68164dba5c2b74a5204850b4cf"},
- {file = "coverage-7.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8dca5590fec7a89ed6826fce625595279e586ead52e9e958d3237821fbc750c"},
- {file = "coverage-7.13.1-cp312-cp312-win32.whl", hash = "sha256:ff86d4e85188bba72cfb876df3e11fa243439882c55957184af44a35bd5880b7"},
- {file = "coverage-7.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:16cc1da46c04fb0fb128b4dc430b78fa2aba8a6c0c9f8eb391fd5103409a6ac6"},
- {file = "coverage-7.13.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d9bc218650022a768f3775dd7fdac1886437325d8d295d923ebcfef4892ad5c"},
- {file = "coverage-7.13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb237bfd0ef4d5eb6a19e29f9e528ac67ac3be932ea6b44fb6cc09b9f3ecff78"},
- {file = "coverage-7.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1dcb645d7e34dcbcc96cd7c132b1fc55c39263ca62eb961c064eb3928997363b"},
- {file = "coverage-7.13.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3d42df8201e00384736f0df9be2ced39324c3907607d17d50d50116c989d84cd"},
- {file = "coverage-7.13.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa3edde1aa8807de1d05934982416cb3ec46d1d4d91e280bcce7cca01c507992"},
- {file = "coverage-7.13.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9edd0e01a343766add6817bc448408858ba6b489039eaaa2018474e4001651a4"},
- {file = "coverage-7.13.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:985b7836931d033570b94c94713c6dba5f9d3ff26045f72c3e5dbc5fe3361e5a"},
- {file = "coverage-7.13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ffed1e4980889765c84a5d1a566159e363b71d6b6fbaf0bebc9d3c30bc016766"},
- {file = "coverage-7.13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8842af7f175078456b8b17f1b73a0d16a65dcbdc653ecefeb00a56b3c8c298c4"},
- {file = "coverage-7.13.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ccd7a6fca48ca9c131d9b0a2972a581e28b13416fc313fb98b6d24a03ce9a398"},
- {file = "coverage-7.13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0403f647055de2609be776965108447deb8e384fe4a553c119e3ff6bfbab4784"},
- {file = "coverage-7.13.1-cp313-cp313-win32.whl", hash = "sha256:549d195116a1ba1e1ae2f5ca143f9777800f6636eab917d4f02b5310d6d73461"},
- {file = "coverage-7.13.1-cp313-cp313-win_amd64.whl", hash = "sha256:5899d28b5276f536fcf840b18b61a9fce23cc3aec1d114c44c07fe94ebeaa500"},
- {file = "coverage-7.13.1-cp313-cp313-win_arm64.whl", hash = "sha256:868a2fae76dfb06e87291bcbd4dcbcc778a8500510b618d50496e520bd94d9b9"},
- {file = "coverage-7.13.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:67170979de0dacac3f3097d02b0ad188d8edcea44ccc44aaa0550af49150c7dc"},
- {file = "coverage-7.13.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f80e2bb21bfab56ed7405c2d79d34b5dc0bc96c2c1d2a067b643a09fb756c43a"},
- {file = "coverage-7.13.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f83351e0f7dcdb14d7326c3d8d8c4e915fa685cbfdc6281f9470d97a04e9dfe4"},
- {file = "coverage-7.13.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb3f6562e89bad0110afbe64e485aac2462efdce6232cdec7862a095dc3412f6"},
- {file = "coverage-7.13.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77545b5dcda13b70f872c3b5974ac64c21d05e65b1590b441c8560115dc3a0d1"},
- {file = "coverage-7.13.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4d240d260a1aed814790bbe1f10a5ff31ce6c21bc78f0da4a1e8268d6c80dbd"},
- {file = "coverage-7.13.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d2287ac9360dec3837bfdad969963a5d073a09a85d898bd86bea82aa8876ef3c"},
- {file = "coverage-7.13.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0d2c11f3ea4db66b5cbded23b20185c35066892c67d80ec4be4bab257b9ad1e0"},
- {file = "coverage-7.13.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:3fc6a169517ca0d7ca6846c3c5392ef2b9e38896f61d615cb75b9e7134d4ee1e"},
- {file = "coverage-7.13.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d10a2ed46386e850bb3de503a54f9fe8192e5917fcbb143bfef653a9355e9a53"},
- {file = "coverage-7.13.1-cp313-cp313t-win32.whl", hash = "sha256:75a6f4aa904301dab8022397a22c0039edc1f51e90b83dbd4464b8a38dc87842"},
- {file = "coverage-7.13.1-cp313-cp313t-win_amd64.whl", hash = "sha256:309ef5706e95e62578cda256b97f5e097916a2c26247c287bbe74794e7150df2"},
- {file = "coverage-7.13.1-cp313-cp313t-win_arm64.whl", hash = "sha256:92f980729e79b5d16d221038dbf2e8f9a9136afa072f9d5d6ed4cb984b126a09"},
- {file = "coverage-7.13.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:97ab3647280d458a1f9adb85244e81587505a43c0c7cff851f5116cd2814b894"},
- {file = "coverage-7.13.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8f572d989142e0908e6acf57ad1b9b86989ff057c006d13b76c146ec6a20216a"},
- {file = "coverage-7.13.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d72140ccf8a147e94274024ff6fd8fb7811354cf7ef88b1f0a988ebaa5bc774f"},
- {file = "coverage-7.13.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3c9f051b028810f5a87c88e5d6e9af3c0ff32ef62763bf15d29f740453ca909"},
- {file = "coverage-7.13.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f398ba4df52d30b1763f62eed9de5620dcde96e6f491f4c62686736b155aa6e4"},
- {file = "coverage-7.13.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:132718176cc723026d201e347f800cd1a9e4b62ccd3f82476950834dad501c75"},
- {file = "coverage-7.13.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e549d642426e3579b3f4b92d0431543b012dcb6e825c91619d4e93b7363c3f9"},
- {file = "coverage-7.13.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:90480b2134999301eea795b3a9dbf606c6fbab1b489150c501da84a959442465"},
- {file = "coverage-7.13.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e825dbb7f84dfa24663dd75835e7257f8882629fc11f03ecf77d84a75134b864"},
- {file = "coverage-7.13.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:623dcc6d7a7ba450bbdbeedbaa0c42b329bdae16491af2282f12a7e809be7eb9"},
- {file = "coverage-7.13.1-cp314-cp314-win32.whl", hash = "sha256:6e73ebb44dca5f708dc871fe0b90cf4cff1a13f9956f747cc87b535a840386f5"},
- {file = "coverage-7.13.1-cp314-cp314-win_amd64.whl", hash = "sha256:be753b225d159feb397bd0bf91ae86f689bad0da09d3b301478cd39b878ab31a"},
- {file = "coverage-7.13.1-cp314-cp314-win_arm64.whl", hash = "sha256:228b90f613b25ba0019361e4ab81520b343b622fc657daf7e501c4ed6a2366c0"},
- {file = "coverage-7.13.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:60cfb538fe9ef86e5b2ab0ca8fc8d62524777f6c611dcaf76dc16fbe9b8e698a"},
- {file = "coverage-7.13.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:57dfc8048c72ba48a8c45e188d811e5efd7e49b387effc8fb17e97936dde5bf6"},
- {file = "coverage-7.13.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3f2f725aa3e909b3c5fdb8192490bdd8e1495e85906af74fe6e34a2a77ba0673"},
- {file = "coverage-7.13.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ee68b21909686eeb21dfcba2c3b81fee70dcf38b140dcd5aa70680995fa3aa5"},
- {file = "coverage-7.13.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:724b1b270cb13ea2e6503476e34541a0b1f62280bc997eab443f87790202033d"},
- {file = "coverage-7.13.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:916abf1ac5cf7eb16bc540a5bf75c71c43a676f5c52fcb9fe75a2bd75fb944e8"},
- {file = "coverage-7.13.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:776483fd35b58d8afe3acbd9988d5de592ab6da2d2a865edfdbc9fdb43e7c486"},
- {file = "coverage-7.13.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b6f3b96617e9852703f5b633ea01315ca45c77e879584f283c44127f0f1ec564"},
- {file = "coverage-7.13.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:bd63e7b74661fed317212fab774e2a648bc4bb09b35f25474f8e3325d2945cd7"},
- {file = "coverage-7.13.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:933082f161bbb3e9f90d00990dc956120f608cdbcaeea15c4d897f56ef4fe416"},
- {file = "coverage-7.13.1-cp314-cp314t-win32.whl", hash = "sha256:18be793c4c87de2965e1c0f060f03d9e5aff66cfeae8e1dbe6e5b88056ec153f"},
- {file = "coverage-7.13.1-cp314-cp314t-win_amd64.whl", hash = "sha256:0e42e0ec0cd3e0d851cb3c91f770c9301f48647cb2877cb78f74bdaa07639a79"},
- {file = "coverage-7.13.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eaecf47ef10c72ece9a2a92118257da87e460e113b83cc0d2905cbbe931792b4"},
- {file = "coverage-7.13.1-py3-none-any.whl", hash = "sha256:2016745cb3ba554469d02819d78958b571792bb68e31302610e898f80dd3a573"},
- {file = "coverage-7.13.1.tar.gz", hash = "sha256:b7593fe7eb5feaa3fbb461ac79aac9f9fc0387a5ca8080b0c6fe2ca27b091afd"},
+ {file = "coverage-7.13.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f4af3b01763909f477ea17c962e2cca8f39b350a4e46e3a30838b2c12e31b81b"},
+ {file = "coverage-7.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:36393bd2841fa0b59498f75466ee9bdec4f770d3254f031f23e8fd8e140ffdd2"},
+ {file = "coverage-7.13.2-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9cc7573518b7e2186bd229b1a0fe24a807273798832c27032c4510f47ffdb896"},
+ {file = "coverage-7.13.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ca9566769b69a5e216a4e176d54b9df88f29d750c5b78dbb899e379b4e14b30c"},
+ {file = "coverage-7.13.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c9bdea644e94fd66d75a6f7e9a97bb822371e1fe7eadae2cacd50fcbc28e4dc"},
+ {file = "coverage-7.13.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5bd447332ec4f45838c1ad42268ce21ca87c40deb86eabd59888859b66be22a5"},
+ {file = "coverage-7.13.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7c79ad5c28a16a1277e1187cf83ea8dafdcc689a784228a7d390f19776db7c31"},
+ {file = "coverage-7.13.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:76e06ccacd1fb6ada5d076ed98a8c6f66e2e6acd3df02819e2ee29fd637b76ad"},
+ {file = "coverage-7.13.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:49d49e9a5e9f4dc3d3dac95278a020afa6d6bdd41f63608a76fa05a719d5b66f"},
+ {file = "coverage-7.13.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ed2bce0e7bfa53f7b0b01c722da289ef6ad4c18ebd52b1f93704c21f116360c8"},
+ {file = "coverage-7.13.2-cp310-cp310-win32.whl", hash = "sha256:1574983178b35b9af4db4a9f7328a18a14a0a0ce76ffaa1c1bacb4cc82089a7c"},
+ {file = "coverage-7.13.2-cp310-cp310-win_amd64.whl", hash = "sha256:a360a8baeb038928ceb996f5623a4cd508728f8f13e08d4e96ce161702f3dd99"},
+ {file = "coverage-7.13.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:060ebf6f2c51aff5ba38e1f43a2095e087389b1c69d559fde6049a4b0001320e"},
+ {file = "coverage-7.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1ea8ca9db5e7469cd364552985e15911548ea5b69c48a17291f0cac70484b2e"},
+ {file = "coverage-7.13.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b780090d15fd58f07cf2011943e25a5f0c1c894384b13a216b6c86c8a8a7c508"},
+ {file = "coverage-7.13.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:88a800258d83acb803c38175b4495d293656d5fac48659c953c18e5f539a274b"},
+ {file = "coverage-7.13.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6326e18e9a553e674d948536a04a80d850a5eeefe2aae2e6d7cf05d54046c01b"},
+ {file = "coverage-7.13.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:59562de3f797979e1ff07c587e2ac36ba60ca59d16c211eceaa579c266c5022f"},
+ {file = "coverage-7.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:27ba1ed6f66b0e2d61bfa78874dffd4f8c3a12f8e2b5410e515ab345ba7bc9c3"},
+ {file = "coverage-7.13.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8be48da4d47cc68754ce643ea50b3234557cbefe47c2f120495e7bd0a2756f2b"},
+ {file = "coverage-7.13.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2a47a4223d3361b91176aedd9d4e05844ca67d7188456227b6bf5e436630c9a1"},
+ {file = "coverage-7.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c6f141b468740197d6bd38f2b26ade124363228cc3f9858bd9924ab059e00059"},
+ {file = "coverage-7.13.2-cp311-cp311-win32.whl", hash = "sha256:89567798404af067604246e01a49ef907d112edf2b75ef814b1364d5ce267031"},
+ {file = "coverage-7.13.2-cp311-cp311-win_amd64.whl", hash = "sha256:21dd57941804ae2ac7e921771a5e21bbf9aabec317a041d164853ad0a96ce31e"},
+ {file = "coverage-7.13.2-cp311-cp311-win_arm64.whl", hash = "sha256:10758e0586c134a0bafa28f2d37dd2cdb5e4a90de25c0fc0c77dabbad46eca28"},
+ {file = "coverage-7.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f106b2af193f965d0d3234f3f83fc35278c7fb935dfbde56ae2da3dd2c03b84d"},
+ {file = "coverage-7.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78f45d21dc4d5d6bd29323f0320089ef7eae16e4bef712dff79d184fa7330af3"},
+ {file = "coverage-7.13.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fae91dfecd816444c74531a9c3d6ded17a504767e97aa674d44f638107265b99"},
+ {file = "coverage-7.13.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:264657171406c114787b441484de620e03d8f7202f113d62fcd3d9688baa3e6f"},
+ {file = "coverage-7.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae47d8dcd3ded0155afbb59c62bd8ab07ea0fd4902e1c40567439e6db9dcaf2f"},
+ {file = "coverage-7.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8a0b33e9fd838220b007ce8f299114d406c1e8edb21336af4c97a26ecfd185aa"},
+ {file = "coverage-7.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b3becbea7f3ce9a2d4d430f223ec15888e4deb31395840a79e916368d6004cce"},
+ {file = "coverage-7.13.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f819c727a6e6eeb8711e4ce63d78c620f69630a2e9d53bc95ca5379f57b6ba94"},
+ {file = "coverage-7.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:4f7b71757a3ab19f7ba286e04c181004c1d61be921795ee8ba6970fd0ec91da5"},
+ {file = "coverage-7.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b7fc50d2afd2e6b4f6f2f403b70103d280a8e0cb35320cbbe6debcda02a1030b"},
+ {file = "coverage-7.13.2-cp312-cp312-win32.whl", hash = "sha256:292250282cf9bcf206b543d7608bda17ca6fc151f4cbae949fc7e115112fbd41"},
+ {file = "coverage-7.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:eeea10169fac01549a7921d27a3e517194ae254b542102267bef7a93ed38c40e"},
+ {file = "coverage-7.13.2-cp312-cp312-win_arm64.whl", hash = "sha256:2a5b567f0b635b592c917f96b9a9cb3dbd4c320d03f4bf94e9084e494f2e8894"},
+ {file = "coverage-7.13.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ed75de7d1217cf3b99365d110975f83af0528c849ef5180a12fd91b5064df9d6"},
+ {file = "coverage-7.13.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:97e596de8fa9bada4d88fde64a3f4d37f1b6131e4faa32bad7808abc79887ddc"},
+ {file = "coverage-7.13.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:68c86173562ed4413345410c9480a8d64864ac5e54a5cda236748031e094229f"},
+ {file = "coverage-7.13.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7be4d613638d678b2b3773b8f687537b284d7074695a43fe2fbbfc0e31ceaed1"},
+ {file = "coverage-7.13.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d7f63ce526a96acd0e16c4af8b50b64334239550402fb1607ce6a584a6d62ce9"},
+ {file = "coverage-7.13.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:406821f37f864f968e29ac14c3fccae0fec9fdeba48327f0341decf4daf92d7c"},
+ {file = "coverage-7.13.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ee68e5a4e3e5443623406b905db447dceddffee0dceb39f4e0cd9ec2a35004b5"},
+ {file = "coverage-7.13.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2ee0e58cca0c17dd9c6c1cdde02bb705c7b3fbfa5f3b0b5afeda20d4ebff8ef4"},
+ {file = "coverage-7.13.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:6e5bbb5018bf76a56aabdb64246b5288d5ae1b7d0dd4d0534fe86df2c2992d1c"},
+ {file = "coverage-7.13.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a55516c68ef3e08e134e818d5e308ffa6b1337cc8b092b69b24287bf07d38e31"},
+ {file = "coverage-7.13.2-cp313-cp313-win32.whl", hash = "sha256:5b20211c47a8abf4abc3319d8ce2464864fa9f30c5fcaf958a3eed92f4f1fef8"},
+ {file = "coverage-7.13.2-cp313-cp313-win_amd64.whl", hash = "sha256:14f500232e521201cf031549fb1ebdfc0a40f401cf519157f76c397e586c3beb"},
+ {file = "coverage-7.13.2-cp313-cp313-win_arm64.whl", hash = "sha256:9779310cb5a9778a60c899f075a8514c89fa6d10131445c2207fc893e0b14557"},
+ {file = "coverage-7.13.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e64fa5a1e41ce5df6b547cbc3d3699381c9e2c2c369c67837e716ed0f549d48e"},
+ {file = "coverage-7.13.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b01899e82a04085b6561eb233fd688474f57455e8ad35cd82286463ba06332b7"},
+ {file = "coverage-7.13.2-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:838943bea48be0e2768b0cf7819544cdedc1bbb2f28427eabb6eb8c9eb2285d3"},
+ {file = "coverage-7.13.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:93d1d25ec2b27e90bcfef7012992d1f5121b51161b8bffcda756a816cf13c2c3"},
+ {file = "coverage-7.13.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93b57142f9621b0d12349c43fc7741fe578e4bc914c1e5a54142856cfc0bf421"},
+ {file = "coverage-7.13.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f06799ae1bdfff7ccb8665d75f8291c69110ba9585253de254688aa8a1ccc6c5"},
+ {file = "coverage-7.13.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7f9405ab4f81d490811b1d91c7a20361135a2df4c170e7f0b747a794da5b7f23"},
+ {file = "coverage-7.13.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f9ab1d5b86f8fbc97a5b3cd6280a3fd85fef3b028689d8a2c00918f0d82c728c"},
+ {file = "coverage-7.13.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:f674f59712d67e841525b99e5e2b595250e39b529c3bda14764e4f625a3fa01f"},
+ {file = "coverage-7.13.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c6cadac7b8ace1ba9144feb1ae3cb787a6065ba6d23ffc59a934b16406c26573"},
+ {file = "coverage-7.13.2-cp313-cp313t-win32.whl", hash = "sha256:14ae4146465f8e6e6253eba0cccd57423e598a4cb925958b240c805300918343"},
+ {file = "coverage-7.13.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9074896edd705a05769e3de0eac0a8388484b503b68863dd06d5e473f874fd47"},
+ {file = "coverage-7.13.2-cp313-cp313t-win_arm64.whl", hash = "sha256:69e526e14f3f854eda573d3cf40cffd29a1a91c684743d904c33dbdcd0e0f3e7"},
+ {file = "coverage-7.13.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:387a825f43d680e7310e6f325b2167dd093bc8ffd933b83e9aa0983cf6e0a2ef"},
+ {file = "coverage-7.13.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f0d7fea9d8e5d778cd5a9e8fc38308ad688f02040e883cdc13311ef2748cb40f"},
+ {file = "coverage-7.13.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e080afb413be106c95c4ee96b4fffdc9e2fa56a8bbf90b5c0918e5c4449412f5"},
+ {file = "coverage-7.13.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a7fc042ba3c7ce25b8a9f097eb0f32a5ce1ccdb639d9eec114e26def98e1f8a4"},
+ {file = "coverage-7.13.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d0ba505e021557f7f8173ee8cd6b926373d8653e5ff7581ae2efce1b11ef4c27"},
+ {file = "coverage-7.13.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7de326f80e3451bd5cc7239ab46c73ddb658fe0b7649476bc7413572d36cd548"},
+ {file = "coverage-7.13.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:abaea04f1e7e34841d4a7b343904a3f59481f62f9df39e2cd399d69a187a9660"},
+ {file = "coverage-7.13.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9f93959ee0c604bccd8e0697be21de0887b1f73efcc3aa73a3ec0fd13feace92"},
+ {file = "coverage-7.13.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:13fe81ead04e34e105bf1b3c9f9cdf32ce31736ee5d90a8d2de02b9d3e1bcb82"},
+ {file = "coverage-7.13.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d6d16b0f71120e365741bca2cb473ca6fe38930bc5431c5e850ba949f708f892"},
+ {file = "coverage-7.13.2-cp314-cp314-win32.whl", hash = "sha256:9b2f4714bb7d99ba3790ee095b3b4ac94767e1347fe424278a0b10acb3ff04fe"},
+ {file = "coverage-7.13.2-cp314-cp314-win_amd64.whl", hash = "sha256:e4121a90823a063d717a96e0a0529c727fb31ea889369a0ee3ec00ed99bf6859"},
+ {file = "coverage-7.13.2-cp314-cp314-win_arm64.whl", hash = "sha256:6873f0271b4a15a33e7590f338d823f6f66f91ed147a03938d7ce26efd04eee6"},
+ {file = "coverage-7.13.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f61d349f5b7cd95c34017f1927ee379bfbe9884300d74e07cf630ccf7a610c1b"},
+ {file = "coverage-7.13.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a43d34ce714f4ca674c0d90beb760eb05aad906f2c47580ccee9da8fe8bfb417"},
+ {file = "coverage-7.13.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bff1b04cb9d4900ce5c56c4942f047dc7efe57e2608cb7c3c8936e9970ccdbee"},
+ {file = "coverage-7.13.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6ae99e4560963ad8e163e819e5d77d413d331fd00566c1e0856aa252303552c1"},
+ {file = "coverage-7.13.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e79a8c7d461820257d9aa43716c4efc55366d7b292e46b5b37165be1d377405d"},
+ {file = "coverage-7.13.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:060ee84f6a769d40c492711911a76811b4befb6fba50abb450371abb720f5bd6"},
+ {file = "coverage-7.13.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3bca209d001fd03ea2d978f8a4985093240a355c93078aee3f799852c23f561a"},
+ {file = "coverage-7.13.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:6b8092aa38d72f091db61ef83cb66076f18f02da3e1a75039a4f218629600e04"},
+ {file = "coverage-7.13.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4a3158dc2dcce5200d91ec28cd315c999eebff355437d2765840555d765a6e5f"},
+ {file = "coverage-7.13.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3973f353b2d70bd9796cc12f532a05945232ccae966456c8ed7034cb96bbfd6f"},
+ {file = "coverage-7.13.2-cp314-cp314t-win32.whl", hash = "sha256:79f6506a678a59d4ded048dc72f1859ebede8ec2b9a2d509ebe161f01c2879d3"},
+ {file = "coverage-7.13.2-cp314-cp314t-win_amd64.whl", hash = "sha256:196bfeabdccc5a020a57d5a368c681e3a6ceb0447d153aeccc1ab4d70a5032ba"},
+ {file = "coverage-7.13.2-cp314-cp314t-win_arm64.whl", hash = "sha256:69269ab58783e090bfbf5b916ab3d188126e22d6070bbfc93098fdd474ef937c"},
+ {file = "coverage-7.13.2-py3-none-any.whl", hash = "sha256:40ce1ea1e25125556d8e76bd0b61500839a07944cc287ac21d5626f3e620cad5"},
+ {file = "coverage-7.13.2.tar.gz", hash = "sha256:044c6951ec37146b72a50cc81ef02217d27d4c3640efd2640311393cbbf143d3"},
]
[package.extras]
@@ -1277,14 +1277,14 @@ dev = ["mypy (>=1.15)"]
[[package]]
name = "elevenlabs"
-version = "2.31.0"
+version = "2.32.0"
description = ""
optional = false
python-versions = "<4.0,>=3.8"
groups = ["video"]
files = [
- {file = "elevenlabs-2.31.0-py3-none-any.whl", hash = "sha256:163062ab3c8da274a8fa43887974658e0b670b81ab887fbf53579c29e90dd433"},
- {file = "elevenlabs-2.31.0.tar.gz", hash = "sha256:709eca626b67e19b379a099f46af608786f269c3d8824ff1adc04749f7d8b23b"},
+ {file = "elevenlabs-2.32.0-py3-none-any.whl", hash = "sha256:396c8ff4a229a88ea3120e02c44ef840dda057c7f439b9fa070222dc4b644a4d"},
+ {file = "elevenlabs-2.32.0.tar.gz", hash = "sha256:b3f7d41c12a1054b0b0130555099b6b8011cf134239ecedb1d4286e96461fd36"},
]
[package.dependencies]
@@ -1638,61 +1638,66 @@ files = [
[[package]]
name = "greenlet"
-version = "3.3.0"
+version = "3.3.1"
description = "Lightweight in-process concurrent programming"
optional = false
python-versions = ">=3.10"
groups = ["main"]
markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""
files = [
- {file = "greenlet-3.3.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:6f8496d434d5cb2dce025773ba5597f71f5410ae499d5dd9533e0653258cdb3d"},
- {file = "greenlet-3.3.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b96dc7eef78fd404e022e165ec55327f935b9b52ff355b067eb4a0267fc1cffb"},
- {file = "greenlet-3.3.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73631cd5cccbcfe63e3f9492aaa664d278fda0ce5c3d43aeda8e77317e38efbd"},
- {file = "greenlet-3.3.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b299a0cb979f5d7197442dccc3aee67fce53500cd88951b7e6c35575701c980b"},
- {file = "greenlet-3.3.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7dee147740789a4632cace364816046e43310b59ff8fb79833ab043aefa72fd5"},
- {file = "greenlet-3.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:39b28e339fc3c348427560494e28d8a6f3561c8d2bcf7d706e1c624ed8d822b9"},
- {file = "greenlet-3.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b3c374782c2935cc63b2a27ba8708471de4ad1abaa862ffdb1ef45a643ddbb7d"},
- {file = "greenlet-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:b49e7ed51876b459bd645d83db257f0180e345d3f768a35a85437a24d5a49082"},
- {file = "greenlet-3.3.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e29f3018580e8412d6aaf5641bb7745d38c85228dacf51a73bd4e26ddf2a6a8e"},
- {file = "greenlet-3.3.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a687205fb22794e838f947e2194c0566d3812966b41c78709554aa883183fb62"},
- {file = "greenlet-3.3.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4243050a88ba61842186cb9e63c7dfa677ec146160b0efd73b855a3d9c7fcf32"},
- {file = "greenlet-3.3.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:670d0f94cd302d81796e37299bcd04b95d62403883b24225c6b5271466612f45"},
- {file = "greenlet-3.3.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cb3a8ec3db4a3b0eb8a3c25436c2d49e3505821802074969db017b87bc6a948"},
- {file = "greenlet-3.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2de5a0b09eab81fc6a382791b995b1ccf2b172a9fec934747a7a23d2ff291794"},
- {file = "greenlet-3.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4449a736606bd30f27f8e1ff4678ee193bc47f6ca810d705981cfffd6ce0d8c5"},
- {file = "greenlet-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:7652ee180d16d447a683c04e4c5f6441bae7ba7b17ffd9f6b3aff4605e9e6f71"},
- {file = "greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb"},
- {file = "greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3"},
- {file = "greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655"},
- {file = "greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7"},
- {file = "greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b"},
- {file = "greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53"},
- {file = "greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614"},
- {file = "greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39"},
- {file = "greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739"},
- {file = "greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808"},
- {file = "greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54"},
- {file = "greenlet-3.3.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492"},
- {file = "greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527"},
- {file = "greenlet-3.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39"},
- {file = "greenlet-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8"},
- {file = "greenlet-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38"},
- {file = "greenlet-3.3.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:60c2ef0f578afb3c8d92ea07ad327f9a062547137afe91f38408f08aacab667f"},
- {file = "greenlet-3.3.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a5d554d0712ba1de0a6c94c640f7aeba3f85b3a6e1f2899c11c2c0428da9365"},
- {file = "greenlet-3.3.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3a898b1e9c5f7307ebbde4102908e6cbfcb9ea16284a3abe15cab996bee8b9b3"},
- {file = "greenlet-3.3.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dcd2bdbd444ff340e8d6bdf54d2f206ccddbb3ccfdcd3c25bf4afaa7b8f0cf45"},
- {file = "greenlet-3.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5773edda4dc00e173820722711d043799d3adb4f01731f40619e07ea2750b955"},
- {file = "greenlet-3.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ac0549373982b36d5fd5d30beb8a7a33ee541ff98d2b502714a09f1169f31b55"},
- {file = "greenlet-3.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d198d2d977460358c3b3a4dc844f875d1adb33817f0613f663a656f463764ccc"},
- {file = "greenlet-3.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:73f51dd0e0bdb596fb0417e475fa3c5e32d4c83638296e560086b8d7da7c4170"},
- {file = "greenlet-3.3.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d6ed6f85fae6cdfdb9ce04c9bf7a08d666cfcfb914e7d006f44f840b46741931"},
- {file = "greenlet-3.3.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9125050fcf24554e69c4cacb086b87b3b55dc395a8b3ebe6487b045b2614388"},
- {file = "greenlet-3.3.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:87e63ccfa13c0a0f6234ed0add552af24cc67dd886731f2261e46e241608bee3"},
- {file = "greenlet-3.3.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2662433acbca297c9153a4023fe2161c8dcfdcc91f10433171cf7e7d94ba2221"},
- {file = "greenlet-3.3.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c6e9b9c1527a78520357de498b0e709fb9e2f49c3a513afd5a249007261911b"},
- {file = "greenlet-3.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:286d093f95ec98fdd92fcb955003b8a3d054b4e2cab3e2707a5039e7b50520fd"},
- {file = "greenlet-3.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c10513330af5b8ae16f023e8ddbfb486ab355d04467c4679c5cfe4659975dd9"},
- {file = "greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb"},
+ {file = "greenlet-3.3.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:04bee4775f40ecefcdaa9d115ab44736cd4b9c5fba733575bfe9379419582e13"},
+ {file = "greenlet-3.3.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50e1457f4fed12a50e427988a07f0f9df53cf0ee8da23fab16e6732c2ec909d4"},
+ {file = "greenlet-3.3.1-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:070472cd156f0656f86f92e954591644e158fd65aa415ffbe2d44ca77656a8f5"},
+ {file = "greenlet-3.3.1-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1108b61b06b5224656121c3c8ee8876161c491cbe74e5c519e0634c837cf93d5"},
+ {file = "greenlet-3.3.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a300354f27dd86bae5fbf7002e6dd2b3255cd372e9242c933faf5e859b703fe"},
+ {file = "greenlet-3.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e84b51cbebf9ae573b5fbd15df88887815e3253fc000a7d0ff95170e8f7e9729"},
+ {file = "greenlet-3.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0093bd1a06d899892427217f0ff2a3c8f306182b8c754336d32e2d587c131b4"},
+ {file = "greenlet-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:7932f5f57609b6a3b82cc11877709aa7a98e3308983ed93552a1c377069b20c8"},
+ {file = "greenlet-3.3.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5fd23b9bc6d37b563211c6abbb1b3cab27db385a4449af5c32e932f93017080c"},
+ {file = "greenlet-3.3.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09f51496a0bfbaa9d74d36a52d2580d1ef5ed4fdfcff0a73730abfbbbe1403dd"},
+ {file = "greenlet-3.3.1-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb0feb07fe6e6a74615ee62a880007d976cf739b6669cce95daa7373d4fc69c5"},
+ {file = "greenlet-3.3.1-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:67ea3fc73c8cd92f42467a72b75e8f05ed51a0e9b1d15398c913416f2dafd49f"},
+ {file = "greenlet-3.3.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:39eda9ba259cc9801da05351eaa8576e9aa83eb9411e8f0c299e05d712a210f2"},
+ {file = "greenlet-3.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e2e7e882f83149f0a71ac822ebf156d902e7a5d22c9045e3e0d1daf59cee2cc9"},
+ {file = "greenlet-3.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:80aa4d79eb5564f2e0a6144fcc744b5a37c56c4a92d60920720e99210d88db0f"},
+ {file = "greenlet-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:32e4ca9777c5addcbf42ff3915d99030d8e00173a56f80001fb3875998fe410b"},
+ {file = "greenlet-3.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:da19609432f353fed186cc1b85e9440db93d489f198b4bdf42ae19cc9d9ac9b4"},
+ {file = "greenlet-3.3.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7e806ca53acf6d15a888405880766ec84721aa4181261cd11a457dfe9a7a4975"},
+ {file = "greenlet-3.3.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d842c94b9155f1c9b3058036c24ffb8ff78b428414a19792b2380be9cecf4f36"},
+ {file = "greenlet-3.3.1-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:20fedaadd422fa02695f82093f9a98bad3dab5fcda793c658b945fcde2ab27ba"},
+ {file = "greenlet-3.3.1-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c620051669fd04ac6b60ebc70478210119c56e2d5d5df848baec4312e260e4ca"},
+ {file = "greenlet-3.3.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14194f5f4305800ff329cbf02c5fcc88f01886cadd29941b807668a45f0d2336"},
+ {file = "greenlet-3.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7b2fe4150a0cf59f847a67db8c155ac36aed89080a6a639e9f16df5d6c6096f1"},
+ {file = "greenlet-3.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49f4ad195d45f4a66a0eb9c1ba4832bb380570d361912fa3554746830d332149"},
+ {file = "greenlet-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cc98b9c4e4870fa983436afa999d4eb16b12872fab7071423d5262fa7120d57a"},
+ {file = "greenlet-3.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:bfb2d1763d777de5ee495c85309460f6fd8146e50ec9d0ae0183dbf6f0a829d1"},
+ {file = "greenlet-3.3.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3"},
+ {file = "greenlet-3.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac"},
+ {file = "greenlet-3.3.1-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd"},
+ {file = "greenlet-3.3.1-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:12184c61e5d64268a160226fb4818af4df02cfead8379d7f8b99a56c3a54ff3e"},
+ {file = "greenlet-3.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3"},
+ {file = "greenlet-3.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951"},
+ {file = "greenlet-3.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2"},
+ {file = "greenlet-3.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946"},
+ {file = "greenlet-3.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d"},
+ {file = "greenlet-3.3.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5"},
+ {file = "greenlet-3.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b"},
+ {file = "greenlet-3.3.1-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e"},
+ {file = "greenlet-3.3.1-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3e0f3878ca3a3ff63ab4ea478585942b53df66ddde327b59ecb191b19dbbd62d"},
+ {file = "greenlet-3.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f"},
+ {file = "greenlet-3.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683"},
+ {file = "greenlet-3.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1"},
+ {file = "greenlet-3.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a"},
+ {file = "greenlet-3.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79"},
+ {file = "greenlet-3.3.1-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242"},
+ {file = "greenlet-3.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774"},
+ {file = "greenlet-3.3.1-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97"},
+ {file = "greenlet-3.3.1-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b9721549a95db96689458a1e0ae32412ca18776ed004463df3a9299c1b257ab"},
+ {file = "greenlet-3.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2"},
+ {file = "greenlet-3.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53"},
+ {file = "greenlet-3.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249"},
+ {file = "greenlet-3.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451"},
+ {file = "greenlet-3.3.1.tar.gz", hash = "sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98"},
]
[package.extras]
@@ -1701,25 +1706,25 @@ test = ["objgraph", "psutil", "setuptools"]
[[package]]
name = "gunicorn"
-version = "23.0.0"
+version = "24.1.1"
description = "WSGI HTTP Server for UNIX"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d"},
- {file = "gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"},
+ {file = "gunicorn-24.1.1-py3-none-any.whl", hash = "sha256:757f6b621fc4f7581a90600b2cd9df593461f06a41d7259cb9b94499dc4095a8"},
+ {file = "gunicorn-24.1.1.tar.gz", hash = "sha256:f006d110e5cb3102859b4f5cd48335dbd9cc28d0d27cd24ddbdafa6c60929408"},
]
[package.dependencies]
packaging = "*"
[package.extras]
-eventlet = ["eventlet (>=0.24.1,!=0.36.0)"]
-gevent = ["gevent (>=1.4.0)"]
+eventlet = ["eventlet (>=0.40.3)"]
+gevent = ["gevent (>=24.10.1)"]
setproctitle = ["setproctitle"]
-testing = ["coverage", "eventlet", "gevent", "pytest", "pytest-cov"]
-tornado = ["tornado (>=0.2)"]
+testing = ["coverage", "eventlet (>=0.40.3)", "gevent (>=24.10.1)", "pytest", "pytest-asyncio", "pytest-cov"]
+tornado = ["tornado (>=6.5.0)"]
[[package]]
name = "h11"
@@ -1993,14 +1998,14 @@ files = [
[[package]]
name = "jmespath"
-version = "1.0.1"
+version = "1.1.0"
description = "JSON Matching Expressions"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
- {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
+ {file = "jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64"},
+ {file = "jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d"},
]
[[package]]
@@ -2454,18 +2459,18 @@ htmlsoup = ["BeautifulSoup4"]
[[package]]
name = "markdown"
-version = "3.10"
+version = "3.10.1"
description = "Python implementation of John Gruber's Markdown."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c"},
- {file = "markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e"},
+ {file = "markdown-3.10.1-py3-none-any.whl", hash = "sha256:867d788939fe33e4b736426f5b9f651ad0c0ae0ecf89df0ca5d1176c70812fe3"},
+ {file = "markdown-3.10.1.tar.gz", hash = "sha256:1c19c10bd5c14ac948c53d0d762a04e2fa35a6d58a6b7b1e6bfcbe6fefc0001a"},
]
[package.extras]
-docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
+docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python] (>=0.28.3)"]
testing = ["coverage", "pyyaml"]
[[package]]
@@ -2589,158 +2594,158 @@ tests = ["pytest", "simplejson"]
[[package]]
name = "multidict"
-version = "6.7.0"
+version = "6.7.1"
description = "multidict implementation"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "multidict-6.7.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9f474ad5acda359c8758c8accc22032c6abe6dc87a8be2440d097785e27a9349"},
- {file = "multidict-6.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a9db5a870f780220e931d0002bbfd88fb53aceb6293251e2c839415c1b20e"},
- {file = "multidict-6.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03ca744319864e92721195fa28c7a3b2bc7b686246b35e4078c1e4d0eb5466d3"},
- {file = "multidict-6.7.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f0e77e3c0008bc9316e662624535b88d360c3a5d3f81e15cf12c139a75250046"},
- {file = "multidict-6.7.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08325c9e5367aa379a3496aa9a022fe8837ff22e00b94db256d3a1378c76ab32"},
- {file = "multidict-6.7.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e2862408c99f84aa571ab462d25236ef9cb12a602ea959ba9c9009a54902fc73"},
- {file = "multidict-6.7.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d72a9a2d885f5c208b0cb91ff2ed43636bb7e345ec839ff64708e04f69a13cc"},
- {file = "multidict-6.7.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:478cc36476687bac1514d651cbbaa94b86b0732fb6855c60c673794c7dd2da62"},
- {file = "multidict-6.7.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6843b28b0364dc605f21481c90fadb5f60d9123b442eb8a726bb74feef588a84"},
- {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23bfeee5316266e5ee2d625df2d2c602b829435fc3a235c2ba2131495706e4a0"},
- {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:680878b9f3d45c31e1f730eef731f9b0bc1da456155688c6745ee84eb818e90e"},
- {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:eb866162ef2f45063acc7a53a88ef6fe8bf121d45c30ea3c9cd87ce7e191a8d4"},
- {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:df0e3bf7993bdbeca5ac25aa859cf40d39019e015c9c91809ba7093967f7a648"},
- {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:661709cdcd919a2ece2234f9bae7174e5220c80b034585d7d8a755632d3e2111"},
- {file = "multidict-6.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:096f52730c3fb8ed419db2d44391932b63891b2c5ed14850a7e215c0ba9ade36"},
- {file = "multidict-6.7.0-cp310-cp310-win32.whl", hash = "sha256:afa8a2978ec65d2336305550535c9c4ff50ee527914328c8677b3973ade52b85"},
- {file = "multidict-6.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:b15b3afff74f707b9275d5ba6a91ae8f6429c3ffb29bbfd216b0b375a56f13d7"},
- {file = "multidict-6.7.0-cp310-cp310-win_arm64.whl", hash = "sha256:4b73189894398d59131a66ff157837b1fafea9974be486d036bb3d32331fdbf0"},
- {file = "multidict-6.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc"},
- {file = "multidict-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721"},
- {file = "multidict-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6"},
- {file = "multidict-6.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c"},
- {file = "multidict-6.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7"},
- {file = "multidict-6.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7"},
- {file = "multidict-6.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9"},
- {file = "multidict-6.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8"},
- {file = "multidict-6.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd"},
- {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb"},
- {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6"},
- {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2"},
- {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff"},
- {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b"},
- {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34"},
- {file = "multidict-6.7.0-cp311-cp311-win32.whl", hash = "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff"},
- {file = "multidict-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81"},
- {file = "multidict-6.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912"},
- {file = "multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184"},
- {file = "multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45"},
- {file = "multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa"},
- {file = "multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7"},
- {file = "multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e"},
- {file = "multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546"},
- {file = "multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4"},
- {file = "multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1"},
- {file = "multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d"},
- {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304"},
- {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12"},
- {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62"},
- {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0"},
- {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a"},
- {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8"},
- {file = "multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4"},
- {file = "multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b"},
- {file = "multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec"},
- {file = "multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6"},
- {file = "multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159"},
- {file = "multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca"},
- {file = "multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8"},
- {file = "multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60"},
- {file = "multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4"},
- {file = "multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f"},
- {file = "multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf"},
- {file = "multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32"},
- {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036"},
- {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec"},
- {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e"},
- {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64"},
- {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd"},
- {file = "multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288"},
- {file = "multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17"},
- {file = "multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390"},
- {file = "multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e"},
- {file = "multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00"},
- {file = "multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb"},
- {file = "multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b"},
- {file = "multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c"},
- {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1"},
- {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b"},
- {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5"},
- {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad"},
- {file = "multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c"},
- {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5"},
- {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10"},
- {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754"},
- {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c"},
- {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762"},
- {file = "multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6"},
- {file = "multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d"},
- {file = "multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6"},
- {file = "multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792"},
- {file = "multidict-6.7.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842"},
- {file = "multidict-6.7.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b"},
- {file = "multidict-6.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38"},
- {file = "multidict-6.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128"},
- {file = "multidict-6.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34"},
- {file = "multidict-6.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99"},
- {file = "multidict-6.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202"},
- {file = "multidict-6.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1"},
- {file = "multidict-6.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3"},
- {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d"},
- {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6"},
- {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7"},
- {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb"},
- {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f"},
- {file = "multidict-6.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f"},
- {file = "multidict-6.7.0-cp314-cp314-win32.whl", hash = "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885"},
- {file = "multidict-6.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c"},
- {file = "multidict-6.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000"},
- {file = "multidict-6.7.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63"},
- {file = "multidict-6.7.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718"},
- {file = "multidict-6.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2"},
- {file = "multidict-6.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e"},
- {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064"},
- {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e"},
- {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd"},
- {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a"},
- {file = "multidict-6.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96"},
- {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e"},
- {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599"},
- {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394"},
- {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38"},
- {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9"},
- {file = "multidict-6.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0"},
- {file = "multidict-6.7.0-cp314-cp314t-win32.whl", hash = "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13"},
- {file = "multidict-6.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd"},
- {file = "multidict-6.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827"},
- {file = "multidict-6.7.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:363eb68a0a59bd2303216d2346e6c441ba10d36d1f9969fcb6f1ba700de7bb5c"},
- {file = "multidict-6.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d874eb056410ca05fed180b6642e680373688efafc7f077b2a2f61811e873a40"},
- {file = "multidict-6.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b55d5497b51afdfde55925e04a022f1de14d4f4f25cdfd4f5d9b0aa96166851"},
- {file = "multidict-6.7.0-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f8e5c0031b90ca9ce555e2e8fd5c3b02a25f14989cbc310701823832c99eb687"},
- {file = "multidict-6.7.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cf41880c991716f3c7cec48e2f19ae4045fc9db5fc9cff27347ada24d710bb5"},
- {file = "multidict-6.7.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cfc12a8630a29d601f48d47787bd7eb730e475e83edb5d6c5084317463373eb"},
- {file = "multidict-6.7.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3996b50c3237c4aec17459217c1e7bbdead9a22a0fcd3c365564fbd16439dde6"},
- {file = "multidict-6.7.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7f5170993a0dd3ab871c74f45c0a21a4e2c37a2f2b01b5f722a2ad9c6650469e"},
- {file = "multidict-6.7.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ec81878ddf0e98817def1e77d4f50dae5ef5b0e4fe796fae3bd674304172416e"},
- {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9281bf5b34f59afbc6b1e477a372e9526b66ca446f4bf62592839c195a718b32"},
- {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:68af405971779d8b37198726f2b6fe3955db846fee42db7a4286fc542203934c"},
- {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3ba3ef510467abb0667421a286dc906e30eb08569365f5cdb131d7aff7c2dd84"},
- {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b61189b29081a20c7e4e0b49b44d5d44bb0dc92be3c6d06a11cc043f81bf9329"},
- {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fb287618b9c7aa3bf8d825f02d9201b2f13078a5ed3b293c8f4d953917d84d5e"},
- {file = "multidict-6.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:521f33e377ff64b96c4c556b81c55d0cfffb96a11c194fd0c3f1e56f3d8dd5a4"},
- {file = "multidict-6.7.0-cp39-cp39-win32.whl", hash = "sha256:ce8fdc2dca699f8dbf055a61d73eaa10482569ad20ee3c36ef9641f69afa8c91"},
- {file = "multidict-6.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:7e73299c99939f089dd9b2120a04a516b95cdf8c1cd2b18c53ebf0de80b1f18f"},
- {file = "multidict-6.7.0-cp39-cp39-win_arm64.whl", hash = "sha256:6bdce131e14b04fd34a809b6380dbfd826065c3e2fe8a50dbae659fa0c390546"},
- {file = "multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3"},
- {file = "multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5"},
+ {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5"},
+ {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8"},
+ {file = "multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872"},
+ {file = "multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991"},
+ {file = "multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03"},
+ {file = "multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981"},
+ {file = "multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6"},
+ {file = "multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190"},
+ {file = "multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92"},
+ {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee"},
+ {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2"},
+ {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568"},
+ {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40"},
+ {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962"},
+ {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505"},
+ {file = "multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122"},
+ {file = "multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df"},
+ {file = "multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db"},
+ {file = "multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d"},
+ {file = "multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e"},
+ {file = "multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855"},
+ {file = "multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3"},
+ {file = "multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e"},
+ {file = "multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a"},
+ {file = "multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8"},
+ {file = "multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0"},
+ {file = "multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144"},
+ {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49"},
+ {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71"},
+ {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3"},
+ {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c"},
+ {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0"},
+ {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa"},
+ {file = "multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a"},
+ {file = "multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b"},
+ {file = "multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6"},
+ {file = "multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172"},
+ {file = "multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd"},
+ {file = "multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7"},
+ {file = "multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53"},
+ {file = "multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75"},
+ {file = "multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b"},
+ {file = "multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733"},
+ {file = "multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a"},
+ {file = "multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961"},
+ {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582"},
+ {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e"},
+ {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3"},
+ {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6"},
+ {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a"},
+ {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba"},
+ {file = "multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511"},
+ {file = "multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19"},
+ {file = "multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf"},
+ {file = "multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23"},
+ {file = "multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2"},
+ {file = "multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445"},
+ {file = "multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177"},
+ {file = "multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23"},
+ {file = "multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060"},
+ {file = "multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d"},
+ {file = "multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed"},
+ {file = "multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429"},
+ {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6"},
+ {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9"},
+ {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c"},
+ {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84"},
+ {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d"},
+ {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33"},
+ {file = "multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3"},
+ {file = "multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5"},
+ {file = "multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df"},
+ {file = "multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1"},
+ {file = "multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963"},
+ {file = "multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34"},
+ {file = "multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65"},
+ {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292"},
+ {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43"},
+ {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca"},
+ {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd"},
+ {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7"},
+ {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3"},
+ {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4"},
+ {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8"},
+ {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c"},
+ {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52"},
+ {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108"},
+ {file = "multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32"},
+ {file = "multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8"},
+ {file = "multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118"},
+ {file = "multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee"},
+ {file = "multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2"},
+ {file = "multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1"},
+ {file = "multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d"},
+ {file = "multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31"},
+ {file = "multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048"},
+ {file = "multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362"},
+ {file = "multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37"},
+ {file = "multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709"},
+ {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0"},
+ {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb"},
+ {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd"},
+ {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601"},
+ {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1"},
+ {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b"},
+ {file = "multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d"},
+ {file = "multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f"},
+ {file = "multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5"},
+ {file = "multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581"},
+ {file = "multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a"},
+ {file = "multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c"},
+ {file = "multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262"},
+ {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59"},
+ {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889"},
+ {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4"},
+ {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d"},
+ {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609"},
+ {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489"},
+ {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c"},
+ {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e"},
+ {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c"},
+ {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9"},
+ {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2"},
+ {file = "multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7"},
+ {file = "multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5"},
+ {file = "multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2"},
+ {file = "multidict-6.7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:65573858d27cdeaca41893185677dc82395159aa28875a8867af66532d413a8f"},
+ {file = "multidict-6.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c524c6fb8fc342793708ab111c4dbc90ff9abd568de220432500e47e990c0358"},
+ {file = "multidict-6.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aa23b001d968faef416ff70dc0f1ab045517b9b42a90edd3e9bcdb06479e31d5"},
+ {file = "multidict-6.7.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6704fa2b7453b2fb121740555fa1ee20cd98c4d011120caf4d2b8d4e7c76eec0"},
+ {file = "multidict-6.7.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:121a34e5bfa410cdf2c8c49716de160de3b1dbcd86b49656f5681e4543bcd1a8"},
+ {file = "multidict-6.7.1-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0"},
+ {file = "multidict-6.7.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e697826df7eb63418ee190fd06ce9f1803593bb4b9517d08c60d9b9a7f69d8f"},
+ {file = "multidict-6.7.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb08271280173720e9fea9ede98e5231defcbad90f1624bea26f32ec8a956e2f"},
+ {file = "multidict-6.7.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6b3228e1d80af737b72925ce5fb4daf5a335e49cd7ab77ed7b9fdfbf58c526e"},
+ {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3943debf0fbb57bdde5901695c11094a9a36723e5c03875f87718ee15ca2f4d2"},
+ {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:98c5787b0a0d9a41d9311eae44c3b76e6753def8d8870ab501320efe75a6a5f8"},
+ {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:08ccb2a6dc72009093ebe7f3f073e5ec5964cba9a706fa94b1a1484039b87941"},
+ {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb351f72c26dc9abe338ca7294661aa22969ad8ffe7ef7d5541d19f368dc854a"},
+ {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ac1c665bad8b5d762f5f85ebe4d94130c26965f11de70c708c75671297c776de"},
+ {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fa6609d0364f4f6f58351b4659a1f3e0e898ba2a8c5cac04cb2c7bc556b0bc5"},
+ {file = "multidict-6.7.1-cp39-cp39-win32.whl", hash = "sha256:6f77ce314a29263e67adadc7e7c1bc699fcb3a305059ab973d038f87caa42ed0"},
+ {file = "multidict-6.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:f537b55778cd3cbee430abe3131255d3a78202e0f9ea7ffc6ada893a4bcaeea4"},
+ {file = "multidict-6.7.1-cp39-cp39-win_arm64.whl", hash = "sha256:749aa54f578f2e5f439538706a475aa844bfa8ef75854b1401e6e528e4937cf9"},
+ {file = "multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56"},
+ {file = "multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d"},
]
[[package]]
@@ -3478,14 +3483,14 @@ files = [
[[package]]
name = "pycparser"
-version = "2.23"
+version = "3.0"
description = "C parser in Python"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.10"
groups = ["main", "video"]
files = [
- {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"},
- {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"},
+ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"},
+ {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"},
]
markers = {main = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"", video = "implementation_name != \"PyPy\""}
@@ -3783,14 +3788,14 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=7.4.0)", "pytest-cov (>=2.10.1)", "
[[package]]
name = "pyparsing"
-version = "3.3.1"
+version = "3.3.2"
description = "pyparsing - Classes and methods to define and execute parsing grammars"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "pyparsing-3.3.1-py3-none-any.whl", hash = "sha256:023b5e7e5520ad96642e2c6db4cb683d3970bd640cdf7115049a6e9c3682df82"},
- {file = "pyparsing-3.3.1.tar.gz", hash = "sha256:47fad0f17ac1e2cad3de3b458570fbc9b03560aa029ed5e16ee5554da9a2251c"},
+ {file = "pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d"},
+ {file = "pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc"},
]
[package.extras]
@@ -4562,31 +4567,31 @@ redis = ">=3.5,<6 || >6"
[[package]]
name = "ruff"
-version = "0.14.13"
+version = "0.14.14"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
- {file = "ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b"},
- {file = "ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed"},
- {file = "ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063"},
- {file = "ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e"},
- {file = "ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09"},
- {file = "ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9"},
- {file = "ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032"},
- {file = "ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c"},
- {file = "ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427"},
- {file = "ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841"},
- {file = "ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c"},
- {file = "ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b"},
- {file = "ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae"},
- {file = "ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e"},
- {file = "ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c"},
- {file = "ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680"},
- {file = "ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef"},
- {file = "ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247"},
- {file = "ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47"},
+ {file = "ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed"},
+ {file = "ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c"},
+ {file = "ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de"},
+ {file = "ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e"},
+ {file = "ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8"},
+ {file = "ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906"},
+ {file = "ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480"},
+ {file = "ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df"},
+ {file = "ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b"},
+ {file = "ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974"},
+ {file = "ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66"},
+ {file = "ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13"},
+ {file = "ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412"},
+ {file = "ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3"},
+ {file = "ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b"},
+ {file = "ruff-0.14.14-py3-none-win32.whl", hash = "sha256:b530c191970b143375b6a68e6f743800b2b786bbcf03a7965b06c4bf04568167"},
+ {file = "ruff-0.14.14-py3-none-win_amd64.whl", hash = "sha256:3dde1435e6b6fe5b66506c1dff67a421d0b7f6488d466f651c07f4cab3bf20fd"},
+ {file = "ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c"},
+ {file = "ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b"},
]
[[package]]
@@ -4609,14 +4614,14 @@ crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"]
[[package]]
name = "sentry-sdk"
-version = "2.49.0"
+version = "2.50.0"
description = "Python client for Sentry (https://sentry.io)"
optional = false
python-versions = ">=3.6"
groups = ["main"]
files = [
- {file = "sentry_sdk-2.49.0-py2.py3-none-any.whl", hash = "sha256:6ea78499133874445a20fe9c826c9e960070abeb7ae0cdf930314ab16bb97aa0"},
- {file = "sentry_sdk-2.49.0.tar.gz", hash = "sha256:c1878599cde410d481c04ef50ee3aedd4f600e4d0d253f4763041e468b332c30"},
+ {file = "sentry_sdk-2.50.0-py2.py3-none-any.whl", hash = "sha256:0ef0ed7168657ceb5a0be081f4102d92042a125462d1d1a29277992e344e749e"},
+ {file = "sentry_sdk-2.50.0.tar.gz", hash = "sha256:873437a989ee1b8b25579847bae8384515bf18cfed231b06c591b735c1781fe3"},
]
[package.dependencies]
@@ -4748,64 +4753,71 @@ files = [
[[package]]
name = "sqlalchemy"
-version = "2.0.45"
+version = "2.0.46"
description = "Database Abstraction Library"
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
- {file = "sqlalchemy-2.0.45-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c64772786d9eee72d4d3784c28f0a636af5b0a29f3fe26ff11f55efe90c0bd85"},
- {file = "sqlalchemy-2.0.45-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7ae64ebf7657395824a19bca98ab10eb9a3ecb026bf09524014f1bb81cb598d4"},
- {file = "sqlalchemy-2.0.45-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f02325709d1b1a1489f23a39b318e175a171497374149eae74d612634b234c0"},
- {file = "sqlalchemy-2.0.45-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2c3684fca8a05f0ac1d9a21c1f4a266983a7ea9180efb80ffeb03861ecd01a0"},
- {file = "sqlalchemy-2.0.45-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040f6f0545b3b7da6b9317fc3e922c9a98fc7243b2a1b39f78390fc0942f7826"},
- {file = "sqlalchemy-2.0.45-cp310-cp310-win32.whl", hash = "sha256:830d434d609fe7bfa47c425c445a8b37929f140a7a44cdaf77f6d34df3a7296a"},
- {file = "sqlalchemy-2.0.45-cp310-cp310-win_amd64.whl", hash = "sha256:0209d9753671b0da74da2cfbb9ecf9c02f72a759e4b018b3ab35f244c91842c7"},
- {file = "sqlalchemy-2.0.45-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e90a344c644a4fa871eb01809c32096487928bd2038bf10f3e4515cb688cc56"},
- {file = "sqlalchemy-2.0.45-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8c8b41b97fba5f62349aa285654230296829672fc9939cd7f35aab246d1c08b"},
- {file = "sqlalchemy-2.0.45-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:12c694ed6468333a090d2f60950e4250b928f457e4962389553d6ba5fe9951ac"},
- {file = "sqlalchemy-2.0.45-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f7d27a1d977a1cfef38a0e2e1ca86f09c4212666ce34e6ae542f3ed0a33bc606"},
- {file = "sqlalchemy-2.0.45-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d62e47f5d8a50099b17e2bfc1b0c7d7ecd8ba6b46b1507b58cc4f05eefc3bb1c"},
- {file = "sqlalchemy-2.0.45-cp311-cp311-win32.whl", hash = "sha256:3c5f76216e7b85770d5bb5130ddd11ee89f4d52b11783674a662c7dd57018177"},
- {file = "sqlalchemy-2.0.45-cp311-cp311-win_amd64.whl", hash = "sha256:a15b98adb7f277316f2c276c090259129ee4afca783495e212048daf846654b2"},
- {file = "sqlalchemy-2.0.45-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3ee2aac15169fb0d45822983631466d60b762085bc4535cd39e66bea362df5f"},
- {file = "sqlalchemy-2.0.45-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba547ac0b361ab4f1608afbc8432db669bd0819b3e12e29fb5fa9529a8bba81d"},
- {file = "sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:215f0528b914e5c75ef2559f69dca86878a3beeb0c1be7279d77f18e8d180ed4"},
- {file = "sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:107029bf4f43d076d4011f1afb74f7c3e2ea029ec82eb23d8527d5e909e97aa6"},
- {file = "sqlalchemy-2.0.45-cp312-cp312-win32.whl", hash = "sha256:0c9f6ada57b58420a2c0277ff853abe40b9e9449f8d7d231763c6bc30f5c4953"},
- {file = "sqlalchemy-2.0.45-cp312-cp312-win_amd64.whl", hash = "sha256:8defe5737c6d2179c7997242d6473587c3beb52e557f5ef0187277009f73e5e1"},
- {file = "sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe187fc31a54d7fd90352f34e8c008cf3ad5d064d08fedd3de2e8df83eb4a1cf"},
- {file = "sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:672c45cae53ba88e0dad74b9027dddd09ef6f441e927786b05bec75d949fbb2e"},
- {file = "sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:470daea2c1ce73910f08caf10575676a37159a6d16c4da33d0033546bddebc9b"},
- {file = "sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9c6378449e0940476577047150fd09e242529b761dc887c9808a9a937fe990c8"},
- {file = "sqlalchemy-2.0.45-cp313-cp313-win32.whl", hash = "sha256:4b6bec67ca45bc166c8729910bd2a87f1c0407ee955df110d78948f5b5827e8a"},
- {file = "sqlalchemy-2.0.45-cp313-cp313-win_amd64.whl", hash = "sha256:afbf47dc4de31fa38fd491f3705cac5307d21d4bb828a4f020ee59af412744ee"},
- {file = "sqlalchemy-2.0.45-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83d7009f40ce619d483d26ac1b757dfe3167b39921379a8bd1b596cf02dab4a6"},
- {file = "sqlalchemy-2.0.45-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d8a2ca754e5415cde2b656c27900b19d50ba076aa05ce66e2207623d3fe41f5a"},
- {file = "sqlalchemy-2.0.45-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f46ec744e7f51275582e6a24326e10c49fbdd3fc99103e01376841213028774"},
- {file = "sqlalchemy-2.0.45-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:883c600c345123c033c2f6caca18def08f1f7f4c3ebeb591a63b6fceffc95cce"},
- {file = "sqlalchemy-2.0.45-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2c0b74aa79e2deade948fe8593654c8ef4228c44ba862bb7c9585c8e0db90f33"},
- {file = "sqlalchemy-2.0.45-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8a420169cef179d4c9064365f42d779f1e5895ad26ca0c8b4c0233920973db74"},
- {file = "sqlalchemy-2.0.45-cp314-cp314-win32.whl", hash = "sha256:e50dcb81a5dfe4b7b4a4aa8f338116d127cb209559124f3694c70d6cd072b68f"},
- {file = "sqlalchemy-2.0.45-cp314-cp314-win_amd64.whl", hash = "sha256:4748601c8ea959e37e03d13dcda4a44837afcd1b21338e637f7c935b8da06177"},
- {file = "sqlalchemy-2.0.45-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd337d3526ec5298f67d6a30bbbe4ed7e5e68862f0bf6dd21d289f8d37b7d60b"},
- {file = "sqlalchemy-2.0.45-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9a62b446b7d86a3909abbcd1cd3cc550a832f99c2bc37c5b22e1925438b9367b"},
- {file = "sqlalchemy-2.0.45-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5964f832431b7cdfaaa22a660b4c7eb1dfcd6ed41375f67fd3e3440fd95cb3cc"},
- {file = "sqlalchemy-2.0.45-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee580ab50e748208754ae8980cec79ec205983d8cf8b3f7c39067f3d9f2c8e22"},
- {file = "sqlalchemy-2.0.45-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13e27397a7810163440c6bfed6b3fe46f1bfb2486eb540315a819abd2c004128"},
- {file = "sqlalchemy-2.0.45-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ed3635353e55d28e7f4a95c8eda98a5cdc0a0b40b528433fbd41a9ae88f55b3d"},
- {file = "sqlalchemy-2.0.45-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:db6834900338fb13a9123307f0c2cbb1f890a8656fcd5e5448ae3ad5bbe8d312"},
- {file = "sqlalchemy-2.0.45-cp38-cp38-win32.whl", hash = "sha256:1d8b4a7a8c9b537509d56d5cd10ecdcfbb95912d72480c8861524efecc6a3fff"},
- {file = "sqlalchemy-2.0.45-cp38-cp38-win_amd64.whl", hash = "sha256:ebd300afd2b62679203435f596b2601adafe546cb7282d5a0cd3ed99e423720f"},
- {file = "sqlalchemy-2.0.45-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d29b2b99d527dbc66dd87c3c3248a5dd789d974a507f4653c969999fc7c1191b"},
- {file = "sqlalchemy-2.0.45-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:59a8b8bd9c6bedf81ad07c8bd5543eedca55fe9b8780b2b628d495ba55f8db1e"},
- {file = "sqlalchemy-2.0.45-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd93c6f5d65f254ceabe97548c709e073d6da9883343adaa51bf1a913ce93f8e"},
- {file = "sqlalchemy-2.0.45-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6d0beadc2535157070c9c17ecf25ecec31e13c229a8f69196d7590bde8082bf1"},
- {file = "sqlalchemy-2.0.45-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e057f928ffe9c9b246a55b469c133b98a426297e1772ad24ce9f0c47d123bd5b"},
- {file = "sqlalchemy-2.0.45-cp39-cp39-win32.whl", hash = "sha256:c1c2091b1489435ff85728fafeb990f073e64f6f5e81d5cd53059773e8521eb6"},
- {file = "sqlalchemy-2.0.45-cp39-cp39-win_amd64.whl", hash = "sha256:56ead1f8dfb91a54a28cd1d072c74b3d635bcffbd25e50786533b822d4f2cde2"},
- {file = "sqlalchemy-2.0.45-py3-none-any.whl", hash = "sha256:5225a288e4c8cc2308dbdd874edad6e7d0fd38eac1e9e5f23503425c8eee20d0"},
- {file = "sqlalchemy-2.0.45.tar.gz", hash = "sha256:1632a4bda8d2d25703fdad6363058d882541bdaaee0e5e3ddfa0cd3229efce88"},
+ {file = "sqlalchemy-2.0.46-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735"},
+ {file = "sqlalchemy-2.0.46-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39"},
+ {file = "sqlalchemy-2.0.46-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f"},
+ {file = "sqlalchemy-2.0.46-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5"},
+ {file = "sqlalchemy-2.0.46-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e"},
+ {file = "sqlalchemy-2.0.46-cp310-cp310-win32.whl", hash = "sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047"},
+ {file = "sqlalchemy-2.0.46-cp310-cp310-win_amd64.whl", hash = "sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061"},
+ {file = "sqlalchemy-2.0.46-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684"},
+ {file = "sqlalchemy-2.0.46-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62"},
+ {file = "sqlalchemy-2.0.46-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f"},
+ {file = "sqlalchemy-2.0.46-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01"},
+ {file = "sqlalchemy-2.0.46-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999"},
+ {file = "sqlalchemy-2.0.46-cp311-cp311-win32.whl", hash = "sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d"},
+ {file = "sqlalchemy-2.0.46-cp311-cp311-win_amd64.whl", hash = "sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597"},
+ {file = "sqlalchemy-2.0.46-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c"},
+ {file = "sqlalchemy-2.0.46-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9"},
+ {file = "sqlalchemy-2.0.46-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b"},
+ {file = "sqlalchemy-2.0.46-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53"},
+ {file = "sqlalchemy-2.0.46-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e"},
+ {file = "sqlalchemy-2.0.46-cp312-cp312-win32.whl", hash = "sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb"},
+ {file = "sqlalchemy-2.0.46-cp312-cp312-win_amd64.whl", hash = "sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313-win32.whl", hash = "sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313-win_amd64.whl", hash = "sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b"},
+ {file = "sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314-win32.whl", hash = "sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314-win_amd64.whl", hash = "sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede"},
+ {file = "sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330"},
+ {file = "sqlalchemy-2.0.46-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545"},
+ {file = "sqlalchemy-2.0.46-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069"},
+ {file = "sqlalchemy-2.0.46-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd"},
+ {file = "sqlalchemy-2.0.46-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5"},
+ {file = "sqlalchemy-2.0.46-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19"},
+ {file = "sqlalchemy-2.0.46-cp38-cp38-win32.whl", hash = "sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7"},
+ {file = "sqlalchemy-2.0.46-cp38-cp38-win_amd64.whl", hash = "sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe"},
+ {file = "sqlalchemy-2.0.46-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3"},
+ {file = "sqlalchemy-2.0.46-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a"},
+ {file = "sqlalchemy-2.0.46-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce"},
+ {file = "sqlalchemy-2.0.46-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5"},
+ {file = "sqlalchemy-2.0.46-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc"},
+ {file = "sqlalchemy-2.0.46-cp39-cp39-win32.whl", hash = "sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d"},
+ {file = "sqlalchemy-2.0.46-cp39-cp39-win_amd64.whl", hash = "sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be"},
+ {file = "sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e"},
+ {file = "sqlalchemy-2.0.46.tar.gz", hash = "sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7"},
]
[package.dependencies]
@@ -4855,14 +4867,14 @@ doc = ["sphinx"]
[[package]]
name = "strawberry-graphql"
-version = "0.289.0"
+version = "0.289.5"
description = "A library for creating GraphQL APIs"
optional = false
python-versions = "<4.0,>=3.10"
groups = ["main"]
files = [
- {file = "strawberry_graphql-0.289.0-py3-none-any.whl", hash = "sha256:8fd30c3de55bb518dae68088d43259c831a68a1a688870733a6fcba7512368d0"},
- {file = "strawberry_graphql-0.289.0.tar.gz", hash = "sha256:cb5b6718d7f6a99b4a5d6edf0d76a6b4e414e04b1ad93662dff402b52ed565f2"},
+ {file = "strawberry_graphql-0.289.5-py3-none-any.whl", hash = "sha256:293288f849918d93ed17a32b9126b8fe13f8f0c847b5668e3794fa575665bca6"},
+ {file = "strawberry_graphql-0.289.5.tar.gz", hash = "sha256:2e3eea4f4be04a2b3f1d00b6eafe9935b83595873788f799960180fb0d0be680"},
]
[package.dependencies]
@@ -4894,14 +4906,14 @@ sanic = ["sanic (>=20.12.2)"]
[[package]]
name = "strawberry-graphql-django"
-version = "0.73.1"
+version = "0.74.1"
description = "Strawberry GraphQL Django extension"
optional = false
python-versions = "<4.0,>=3.10"
groups = ["main"]
files = [
- {file = "strawberry_graphql_django-0.73.1-py3-none-any.whl", hash = "sha256:cf073975ade25c9c54557fad093113dfb2a4884fdd0abca1df2e320e2bae40e0"},
- {file = "strawberry_graphql_django-0.73.1.tar.gz", hash = "sha256:b3096c2e6abbfa8db6b25fe52393150b1dbe24f13a4c2eb6ac80625b0d933c3b"},
+ {file = "strawberry_graphql_django-0.74.1-py3-none-any.whl", hash = "sha256:8b0d617ce1649cb244a307514613295558801e43bcc7ef8b21b59e93b4c36b2b"},
+ {file = "strawberry_graphql_django-0.74.1.tar.gz", hash = "sha256:cc052fc89aa6da06507088ffd53a6d08612d8b996a4de5dfea22758225766ae2"},
]
[package.dependencies]
@@ -5122,34 +5134,34 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""]
[[package]]
name = "uuid-utils"
-version = "0.13.0"
+version = "0.14.0"
description = "Fast, drop-in replacement for Python's uuid module, powered by Rust."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "uuid_utils-0.13.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:83628283e977fb212e756bc055df8fdd2f9f589a2e539ba1abe755b8ce8df7a4"},
- {file = "uuid_utils-0.13.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c47638ed6334ab19d80f73664f153b04bbb04ab8ce4298d10da6a292d4d21c47"},
- {file = "uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:b276b538c57733ed406948584912da422a604313c71479654848b84b9e19c9b0"},
- {file = "uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_armv7l.whl", hash = "sha256:bdaf2b77e34b199cf04cde28399495fd1ed951de214a4ece1f3919b2f945bb06"},
- {file = "uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_i686.whl", hash = "sha256:eb2f0baf81e82f9769a7684022dca8f3bf801ca1574a3e94df1876e9d6f9271e"},
- {file = "uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_ppc64le.whl", hash = "sha256:6be6c4d11275f5cc402a4fdba6c2b1ce45fd3d99bb78716cd1cc2cbf6802b2ce"},
- {file = "uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:77621cf6ceca7f42173a642a01c01c216f9eaec3b7b65d093d2d6a433ca0a83d"},
- {file = "uuid_utils-0.13.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a5a9eb06c2bb86dd876cd7b2fe927fc8543d14c90d971581db6ffda4a02526f"},
- {file = "uuid_utils-0.13.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:775347c6110fb71360df17aac74132d8d47c1dbe71233ac98197fc872a791fd2"},
- {file = "uuid_utils-0.13.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf95f6370ad1a0910ee7b5ad5228fd19c4ae32fe3627389006adaf519408c41e"},
- {file = "uuid_utils-0.13.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5a88e23e0b2f4203fefe2ccbca5736ee06fcad10e61b5e7e39c8d7904bc13300"},
- {file = "uuid_utils-0.13.0-cp39-abi3-win32.whl", hash = "sha256:3e4f2cc54e6a99c0551158100ead528479ad2596847478cbad624977064ffce3"},
- {file = "uuid_utils-0.13.0-cp39-abi3-win_amd64.whl", hash = "sha256:046cb2756e1597b3de22d24851b769913e192135830486a0a70bf41327f0360c"},
- {file = "uuid_utils-0.13.0-cp39-abi3-win_arm64.whl", hash = "sha256:5447a680df6ef8a5a353976aaf4c97cc3a3a22b1ee13671c44227b921e3ae2a9"},
- {file = "uuid_utils-0.13.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e5182e2d95f38e65f2e5bce90648ef56987443da13e145afcd747e584f9bc69c"},
- {file = "uuid_utils-0.13.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e3909a8a1fbd79d7c8bdc874eeb83e23ccb7a7cb0aa821a49596cc96c0cce84b"},
- {file = "uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.whl", hash = "sha256:5dc4c9f749bd2511b8dcbf0891e658d7d86880022963db050722ad7b502b5e22"},
- {file = "uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_armv7l.whl", hash = "sha256:516adf07f5b2cdb88d50f489c702b5f1a75ae8b2639bfd254f4192d5f7ee261f"},
- {file = "uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_i686.whl", hash = "sha256:aeee3bd89e8de6184a3ab778ce19f5ce9ad32849d1be549516e0ddb257562d8d"},
- {file = "uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_ppc64le.whl", hash = "sha256:97985256c2e59b7caa51f5c8515f64d777328562a9c900ec65e9d627baf72737"},
- {file = "uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:b7ccaa20e24c5f60f41a69ef571ed820737f9b0ade4cbeef56aaa8f80f5aa475"},
- {file = "uuid_utils-0.13.0.tar.gz", hash = "sha256:4c17df6427a9e23a4cd7fb9ee1efb53b8abb078660b9bdb2524ca8595022dfe1"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f6695c0bed8b18a904321e115afe73b34444bc8451d0ce3244a1ec3b84deb0e5"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:4f0a730bbf2d8bb2c11b93e1005e91769f2f533fa1125ed1f00fd15b6fcc732b"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40ce3fd1a4fdedae618fc3edc8faf91897012469169d600133470f49fd699ed3"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:09ae4a98416a440e78f7d9543d11b11cae4bab538b7ed94ec5da5221481748f2"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:971e8c26b90d8ae727e7f2ac3ee23e265971d448b3672882f2eb44828b2b8c3e"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5cde1fa82804a8f9d2907b7aec2009d440062c63f04abbdb825fce717a5e860"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c7343862a2359e0bd48a7f3dfb5105877a1728677818bb694d9f40703264a2db"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c51e4818fdb08ccec12dc7083a01f49507b4608770a0ab22368001685d59381b"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:181bbcccb6f93d80a8504b5bd47b311a1c31395139596edbc47b154b0685b533"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:5c8ae96101c3524ba8dbf762b6f05e9e9d896544786c503a727c5bf5cb9af1a7"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00ac3c6edfdaff7e1eed041f4800ae09a3361287be780d7610a90fdcde9befdc"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-win32.whl", hash = "sha256:ec2fd80adf8e0e6589d40699e6f6df94c93edcc16dd999be0438dd007c77b151"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-win_amd64.whl", hash = "sha256:efe881eb43a5504fad922644cb93d725fd8a6a6d949bd5a4b4b7d1a1587c7fd1"},
+ {file = "uuid_utils-0.14.0-cp39-abi3-win_arm64.whl", hash = "sha256:32b372b8fd4ebd44d3a219e093fe981af4afdeda2994ee7db208ab065cfcd080"},
+ {file = "uuid_utils-0.14.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:762e8d67992ac4d2454e24a141a1c82142b5bde10409818c62adbe9924ebc86d"},
+ {file = "uuid_utils-0.14.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:40be5bf0b13aa849d9062abc86c198be6a25ff35316ce0b89fc25f3bac6d525e"},
+ {file = "uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:191a90a6f3940d1b7322b6e6cceff4dd533c943659e0a15f788674407856a515"},
+ {file = "uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4aa4525f4ad82f9d9c842f9a3703f1539c1808affbaec07bb1b842f6b8b96aa5"},
+ {file = "uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdbd82ff20147461caefc375551595ecf77ebb384e46267f128aca45a0f2cdfc"},
+ {file = "uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eff57e8a5d540006ce73cf0841a643d445afe78ba12e75ac53a95ca2924a56be"},
+ {file = "uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3fd9112ca96978361201e669729784f26c71fecc9c13a7f8a07162c31bd4d1e2"},
+ {file = "uuid_utils-0.14.0.tar.gz", hash = "sha256:fc5bac21e9933ea6c590433c11aa54aaca599f690c08069e364eb13a12f670b4"},
]
[[package]]
@@ -5190,14 +5202,14 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess
[[package]]
name = "weasyprint"
-version = "67.0"
+version = "68.0"
description = "The Awesome Document Factory"
optional = false
python-versions = ">=3.10"
groups = ["video"]
files = [
- {file = "weasyprint-67.0-py3-none-any.whl", hash = "sha256:abc2f40872ea01c29c11f7799dafc4b23c078335bf7777f72a8affeb36e1d201"},
- {file = "weasyprint-67.0.tar.gz", hash = "sha256:fdfbccf700e8086c8fd1607ec42e25d4b584512c29af2d9913587a4e448dead4"},
+ {file = "weasyprint-68.0-py3-none-any.whl", hash = "sha256:c2cb40c71b50837c5971f00171c9e4078e8c9912dd7c217f3e90e068f11e8aa1"},
+ {file = "weasyprint-68.0.tar.gz", hash = "sha256:447f40898b747cb44ac31a5d493d512e7441fd56e13f63744c099383bbf9cda9"},
]
[package.dependencies]
@@ -5212,7 +5224,7 @@ tinyhtml5 = ">=2.0.0b1"
[package.extras]
doc = ["furo", "sphinx"]
-test = ["pytest", "ruff"]
+test = ["Pillow (>=12.1.0)", "pytest", "ruff"]
[[package]]
name = "webencodings"
@@ -5317,18 +5329,21 @@ watchdog = ["watchdog (>=2.3)"]
[[package]]
name = "wheel"
-version = "0.45.1"
-description = "A built-package format for Python"
+version = "0.46.3"
+description = "Command line tool for manipulating wheel files"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248"},
- {file = "wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729"},
+ {file = "wheel-0.46.3-py3-none-any.whl", hash = "sha256:4b399d56c9d9338230118d705d9737a2a468ccca63d5e813e2a4fc7815d8bc4d"},
+ {file = "wheel-0.46.3.tar.gz", hash = "sha256:e3e79874b07d776c40bd6033f8ddf76a7dad46a7b8aa1b2787a83083519a1803"},
]
+[package.dependencies]
+packaging = ">=24.0"
+
[package.extras]
-test = ["pytest (>=6.0.0)", "setuptools (>=65)"]
+test = ["pytest (>=6.0.0)", "setuptools (>=77)"]
[[package]]
name = "wrapt"
@@ -5916,4 +5931,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt
[metadata]
lock-version = "2.1"
python-versions = "^3.13"
-content-hash = "056fb89434bf8f3733c03fce81175250b972bc40299d4894464e5e1d5f121c76"
+content-hash = "eb0a59232bed3fb7c475dfdabb827affb2452e7f3e911011a09c7e409eb6acaf"
diff --git a/backend/pyproject.toml b/backend/pyproject.toml
index 0dfe0eaf6b..631e59d88e 100644
--- a/backend/pyproject.toml
+++ b/backend/pyproject.toml
@@ -24,7 +24,7 @@ django-rq = "^3.1"
django-storages = { extras = [ "s3" ], version = "^1.14.4" }
emoji = "^2.14.1"
geopy = "^2.4.1"
-gunicorn = "^23.0.0"
+gunicorn = "^24.0.0"
humanize = "^4.11.0"
jinja2 = "^3.1.6"
langchain = "^0.3.26"
@@ -49,7 +49,7 @@ sentry-sdk = { extras = [ "django" ], version = "^2.20.0" }
slack-bolt = "^1.22.0"
slack-sdk = "^3.37.0"
strawberry-graphql = { extras = [ "django" ], version = "^0.289.0" }
-strawberry-graphql-django = "^0.73.0"
+strawberry-graphql-django = "^0.74.1"
thefuzz = "^0.22.1"
zappa = "^0.61.4"
@@ -71,7 +71,7 @@ elevenlabs = "^2.27.0"
ffmpeg-python = "^0.2.0"
pillow = "^12.1.0"
pypdfium2 = "^5.2.0"
-weasyprint = "^67.0"
+weasyprint = "^68.0"
[tool.ruff]
target-version = "py313"
@@ -146,6 +146,7 @@ addopts = [
"--cov-fail-under=80",
"--cov-precision=2",
"--cov-report=term-missing",
+ "--cov-report=xml",
"--cov=.",
"--dist=loadscope",
"--durations-min=1",
diff --git a/backend/settings/graphql.py b/backend/settings/graphql.py
index 6020741d74..39eb24ab67 100644
--- a/backend/settings/graphql.py
+++ b/backend/settings/graphql.py
@@ -4,9 +4,9 @@
from strawberry.extensions import QueryDepthLimiter
from strawberry_django.optimizer import DjangoOptimizerExtension
+from apps.api.internal.extensions.cache import CacheExtension
from apps.api.internal.mutations import ApiMutations
from apps.api.internal.queries import ApiKeyQueries
-from apps.common.extensions import CacheExtension
from apps.github.api.internal.queries import GithubQuery
from apps.mentorship.api.internal.mutations import (
ModuleMutation,
diff --git a/backend/tests/apps/api/internal/extensions/__init__.py b/backend/tests/apps/api/internal/extensions/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/backend/tests/apps/common/extensions_test.py b/backend/tests/apps/api/internal/extensions/cache_test.py
similarity index 56%
rename from backend/tests/apps/common/extensions_test.py
rename to backend/tests/apps/api/internal/extensions/cache_test.py
index 3b7bb1c982..d1d0056129 100644
--- a/backend/tests/apps/common/extensions_test.py
+++ b/backend/tests/apps/api/internal/extensions/cache_test.py
@@ -1,51 +1,67 @@
"""Tests for CacheExtension."""
+import datetime
from unittest.mock import MagicMock, patch
+from uuid import UUID
import pytest
+from django.conf import settings
from strawberry.permission import PermissionExtension
-from apps.common.extensions import CacheExtension, get_protected_fields
+from apps.api.internal.extensions.cache import (
+ CacheExtension,
+ generate_key,
+ get_protected_fields,
+ invalidate_module_cache,
+ invalidate_program_cache,
+)
class TestGenerateKey:
- """Test cases for the generate_key method."""
+ """Test cases for the generate_key function."""
- @pytest.fixture
- def extension(self):
- """Return a CacheExtension instance."""
- return CacheExtension()
-
- def test_creates_deterministic_hash(self, extension):
+ def test_creates_deterministic_hash(self):
"""Test that generate_key creates a deterministic hash key."""
- key1 = extension.generate_key("chapter", {"key": "germany"})
- key2 = extension.generate_key("chapter", {"key": "germany"})
+ key1 = generate_key("chapter", {"key": "germany"})
+ key2 = generate_key("chapter", {"key": "germany"})
assert key1 == key2
assert key1.startswith("graphql-")
assert len(key1.split("-")[-1]) == 64 # SHA256 hex digest length
- def test_differs_for_different_field_names(self, extension):
+ def test_differs_for_different_field_names(self):
"""Test that different field names produce different keys."""
- key1 = extension.generate_key("chapter", {"key": "germany"})
- key2 = extension.generate_key("project", {"key": "germany"})
+ key1 = generate_key("chapter", {"key": "germany"})
+ key2 = generate_key("project", {"key": "germany"})
assert key1 != key2
- def test_differs_for_different_args(self, extension):
+ def test_differs_for_different_args(self):
"""Test that different arguments produce different keys."""
- key1 = extension.generate_key("chapter", {"key": "germany"})
- key2 = extension.generate_key("chapter", {"key": "canada"})
+ key1 = generate_key("chapter", {"key": "germany"})
+ key2 = generate_key("chapter", {"key": "canada"})
assert key1 != key2
- def test_sorts_args_for_consistency(self, extension):
+ def test_sorts_args_for_consistency(self):
"""Test that argument order doesn't affect the key."""
- key1 = extension.generate_key("chapter", {"a": "1", "b": "2"})
- key2 = extension.generate_key("chapter", {"b": "2", "a": "1"})
+ key1 = generate_key("chapter", {"a": "1", "b": "2"})
+ key2 = generate_key("chapter", {"b": "2", "a": "1"})
assert key1 == key2
+ def test_serializes_datetime_and_uuid_args(self):
+ """Test that generate_key handles datetime and UUID in args without error."""
+ dt = datetime.datetime(2025, 1, 15, 12, 0, 0, tzinfo=datetime.UTC)
+ uid = UUID("550e8400-e29b-41d4-a716-446655440000")
+ field_args = {"at": dt, "id": uid}
+
+ key1 = generate_key("someField", field_args)
+ key2 = generate_key("someField", field_args)
+
+ assert key1 == key2
+ assert key1.startswith(f"{settings.GRAPHQL_RESOLVER_CACHE_PREFIX}-")
+
class TestGetProtectedFields:
"""Test cases for the get_protected_fields function."""
@@ -90,7 +106,9 @@ class TestResolve:
@pytest.fixture(autouse=True)
def mock_protected_fields(self):
"""Patch get_protected_fields for all tests."""
- with patch("apps.common.extensions.get_protected_fields", return_value=("apiKeys",)):
+ with patch(
+ "apps.api.internal.extensions.cache.get_protected_fields", return_value=("apiKeys",)
+ ):
yield
@pytest.fixture
@@ -140,7 +158,7 @@ def test_skips_protected_fields(self, extension, mock_info, mock_next):
mock_next.assert_called_once()
assert result == mock_next.return_value
- @patch("apps.common.extensions.cache")
+ @patch("apps.api.internal.extensions.cache.cache")
def test_returns_cached_result_on_hit(self, mock_cache, extension, mock_info, mock_next):
"""Test that cached result is returned on cache hit."""
cached_result = {"name": "Cached OWASP"}
@@ -152,7 +170,7 @@ def test_returns_cached_result_on_hit(self, mock_cache, extension, mock_info, mo
mock_cache.get_or_set.assert_called_once()
mock_next.assert_not_called()
- @patch("apps.common.extensions.cache")
+ @patch("apps.api.internal.extensions.cache.cache")
def test_caches_result_on_miss(self, mock_cache, extension, mock_info, mock_next):
"""Test that result is cached on cache miss."""
mock_cache.get_or_set.side_effect = lambda _key, default, _timeout: default()
@@ -161,3 +179,41 @@ def test_caches_result_on_miss(self, mock_cache, extension, mock_info, mock_next
mock_next.assert_called_once()
mock_cache.get_or_set.assert_called_once()
+
+
+class TestInvalidationHelpers:
+ """Test cases for invalidation helper functions."""
+
+ @patch("apps.api.internal.extensions.cache.cache")
+ @patch("apps.api.internal.extensions.cache.generate_key")
+ def test_invalidate_program_cache_uses_camel_case_keys(self, mock_generate_key, mock_cache):
+ """Test that invalidate_program_cache uses correct camelCase keys."""
+ mock_generate_key.side_effect = lambda name, _args: f"{name}-hashed"
+
+ invalidate_program_cache("my-program")
+
+ # Verify calls to generate_key use camelCase 'programKey'
+ assert mock_generate_key.call_count == 2
+ mock_generate_key.assert_any_call("getProgram", {"programKey": "my-program"})
+ mock_generate_key.assert_any_call("getProgramModules", {"programKey": "my-program"})
+
+ assert mock_cache.delete.call_count == 2
+ mock_cache.delete.assert_any_call("getProgram-hashed")
+ mock_cache.delete.assert_any_call("getProgramModules-hashed")
+
+ @patch("apps.api.internal.extensions.cache.cache")
+ @patch("apps.api.internal.extensions.cache.generate_key")
+ def test_invalidate_module_cache_uses_camel_case_keys(self, mock_generate_key, mock_cache):
+ """Test that invalidate_module_cache uses correct camelCase keys."""
+ mock_generate_key.side_effect = lambda name, _args: f"{name}-hashed"
+
+ invalidate_module_cache("module-1", "program-1")
+
+ assert mock_generate_key.call_count == 3
+ mock_generate_key.assert_any_call(
+ "getModule", {"moduleKey": "module-1", "programKey": "program-1"}
+ )
+ mock_generate_key.assert_any_call("getProgram", {"programKey": "program-1"})
+ mock_generate_key.assert_any_call("getProgramModules", {"programKey": "program-1"})
+
+ assert mock_cache.delete.call_count == 3
diff --git a/backend/tests/apps/common/management/commands/purge_data_test.py b/backend/tests/apps/common/management/commands/purge_data_test.py
index b9942eda91..e423fc0e88 100644
--- a/backend/tests/apps/common/management/commands/purge_data_test.py
+++ b/backend/tests/apps/common/management/commands/purge_data_test.py
@@ -1,6 +1,7 @@
from unittest.mock import MagicMock, patch
import pytest
+from psycopg2 import sql
from apps.common.management.commands.purge_data import Command
@@ -48,5 +49,8 @@ def get_app_config_side_effect(app_name):
for app_name in nest_apps:
for model_name in mock_models[app_name]:
table_name = f"{app_name.lower()}_{model_name.lower()}"
- cursor_instance.execute.assert_any_call(f"TRUNCATE TABLE {table_name} CASCADE")
+ expected_query = sql.SQL("TRUNCATE TABLE {} CASCADE").format(
+ sql.Identifier(table_name)
+ )
+ cursor_instance.execute.assert_any_call(expected_query)
mock_print.assert_any_call(f"Purged {app_name}.{model_name}")
diff --git a/backend/tests/apps/github/models/mixins/repository_test.py b/backend/tests/apps/github/models/mixins/repository_test.py
index ef83099886..65cb79a672 100644
--- a/backend/tests/apps/github/models/mixins/repository_test.py
+++ b/backend/tests/apps/github/models/mixins/repository_test.py
@@ -5,31 +5,35 @@
from apps.github.models.mixins.repository import RepositoryIndexMixin
from apps.github.models.release import Release
+COMMITS_COUNT = 100
CONTRIBUTORS_COUNT = 5
FORKS_COUNT = 5
OPEN_ISSUES_COUNT = 5
+REPOSITORY_SIZE = 1024
STARS_COUNT = 5
+SUBSCRIBERS_COUNT = 10
@pytest.fixture
def repository_index_mixin_instance():
instance = RepositoryIndexMixin()
+ instance.commits_count = COMMITS_COUNT
instance.contributors_count = CONTRIBUTORS_COUNT
+ instance.created_at = datetime(2020, 1, 1, tzinfo=UTC)
instance.description = "Description"
instance.forks_count = FORKS_COUNT
+ instance.has_funding_yml = True
instance.languages = ["Python", "JavaScript"]
+ instance.license = "MIT"
instance.name = "Name"
+ instance.nest_key = "nest/key"
instance.open_issues_count = OPEN_ISSUES_COUNT
+ instance.project = None
instance.pushed_at = datetime(2021, 1, 1, tzinfo=UTC)
+ instance.size = REPOSITORY_SIZE
instance.stars_count = STARS_COUNT
+ instance.subscribers_count = SUBSCRIBERS_COUNT
instance.topics = ["Topic1", "Topic2"]
- instance.created_at = datetime(2020, 1, 1, tzinfo=UTC)
- instance.size = 1024
- instance.has_funding_yml = True
- instance.license = "MIT"
- instance.project = None
- instance.commits_count = 100
- instance.nest_key = "nest/key"
return instance
@@ -104,22 +108,22 @@ def test_idx_top_contributors(self, repository_index_mixin_instance, mocker):
@pytest.mark.parametrize(
("attr", "expected"),
[
+ ("idx_commits_count", 100),
("idx_contributors_count", CONTRIBUTORS_COUNT),
+ ("idx_created_at", datetime(2020, 1, 1, tzinfo=UTC).timestamp()),
("idx_description", "Description"),
("idx_forks_count", FORKS_COUNT),
+ ("idx_has_funding_yml", True),
+ ("idx_key", "nest/key"),
("idx_languages", ["Python", "JavaScript"]),
+ ("idx_license", "MIT"),
("idx_name", "Name"),
("idx_open_issues_count", OPEN_ISSUES_COUNT),
("idx_pushed_at", datetime(2021, 1, 1, tzinfo=UTC).timestamp()),
+ ("idx_size", 1024),
("idx_stars_count", STARS_COUNT),
+ ("idx_subscribers_count", SUBSCRIBERS_COUNT),
("idx_topics", ["Topic1", "Topic2"]),
- ("idx_created_at", datetime(2020, 1, 1, tzinfo=UTC).timestamp()),
- ("idx_has_funding_yml", True),
- ("idx_license", "MIT"),
- ("idx_subscribers_count", STARS_COUNT),
- ("idx_commits_count", 100),
- ("idx_size", 1024),
- ("idx_key", "nest/key"),
],
)
def test_repository_index(self, repository_index_mixin_instance, attr, expected):
diff --git a/cspell/Dockerfile b/cspell/Dockerfile
index 1e0069ca51..ae90478620 100644
--- a/cspell/Dockerfile
+++ b/cspell/Dockerfile
@@ -18,6 +18,6 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
WORKDIR /nest
-ENTRYPOINT ["/opt/node/node_modules/.bin/cspell"]
-
USER node
+
+ENTRYPOINT ["/opt/node/node_modules/.bin/cspell"]
diff --git a/cspell/custom-dict.txt b/cspell/custom-dict.txt
index fd69ff3fa0..5a38a7975a 100644
--- a/cspell/custom-dict.txt
+++ b/cspell/custom-dict.txt
@@ -19,6 +19,7 @@ Héllo
Kateryna
NETTACKER
NOASSERTION
+NOSEMGREP
NOSONAR
Nadu
Nominatim
@@ -55,6 +56,7 @@ askowasp
attisdropped
bangbang
bsky
+carryforward
certbot
collectstatic
coraza
@@ -142,6 +144,7 @@ pygoat
pymdownx
pypoetry
pyyaml
+quasis
rediss
relativedelta
repositorycontributor
@@ -152,6 +155,7 @@ saft
sakanashi
samm
schemathesis
+semgrep
seo
skillstruck
slackbot
diff --git a/cspell/package.json b/cspell/package.json
index d31b166e05..02937db6c3 100644
--- a/cspell/package.json
+++ b/cspell/package.json
@@ -3,7 +3,7 @@
"@cspell/dict-aws": "^4.0.17",
"@cspell/dict-data-science": "^2.0.13",
"@cspell/dict-en_us": "^4.4.27",
- "@cspell/dict-fullstack": "^3.2.7",
+ "@cspell/dict-fullstack": "^3.2.8",
"@cspell/dict-golang": "^6.0.26",
"@cspell/dict-k8s": "^1.0.12",
"@cspell/dict-people-names": "^1.1.16",
diff --git a/cspell/pnpm-lock.yaml b/cspell/pnpm-lock.yaml
index 663a888554..ac0ed4e897 100644
--- a/cspell/pnpm-lock.yaml
+++ b/cspell/pnpm-lock.yaml
@@ -18,8 +18,8 @@ importers:
specifier: ^4.4.27
version: 4.4.27
'@cspell/dict-fullstack':
- specifier: ^3.2.7
- version: 3.2.7
+ specifier: ^3.2.8
+ version: 3.2.8
'@cspell/dict-golang':
specifier: ^6.0.26
version: 6.0.26
@@ -134,14 +134,14 @@ packages:
'@cspell/dict-fsharp@1.1.1':
resolution: {integrity: sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==}
- '@cspell/dict-fullstack@3.2.7':
- resolution: {integrity: sha512-IxEk2YAwAJKYCUEgEeOg3QvTL4XLlyArJElFuMQevU1dPgHgzWElFevN5lsTFnvMFA1riYsVinqJJX0BanCFEg==}
+ '@cspell/dict-fullstack@3.2.8':
+ resolution: {integrity: sha512-J6EeoeThvx/DFrcA2rJiCA6vfqwJMbkG0IcXhlsmRZmasIpanmxgt90OEaUazbZahFiuJT8wrhgQ1QgD1MsqBw==}
'@cspell/dict-gaming-terms@1.1.2':
resolution: {integrity: sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==}
- '@cspell/dict-git@3.0.7':
- resolution: {integrity: sha512-odOwVKgfxCQfiSb+nblQZc4ErXmnWEnv8XwkaI4sNJ7cNmojnvogYVeMqkXPjvfrgEcizEEA4URRD2Ms5PDk1w==}
+ '@cspell/dict-git@3.1.0':
+ resolution: {integrity: sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ==}
'@cspell/dict-golang@6.0.26':
resolution: {integrity: sha512-YKA7Xm5KeOd14v5SQ4ll6afe9VSy3a2DWM7L9uBq4u3lXToRBQ1W5PRa+/Q9udd+DTURyVVnQ+7b9cnOlNxaRg==}
@@ -193,11 +193,11 @@ packages:
'@cspell/dict-monkeyc@1.0.12':
resolution: {integrity: sha512-MN7Vs11TdP5mbdNFQP5x2Ac8zOBm97ARg6zM5Sb53YQt/eMvXOMvrep7+/+8NJXs0jkp70bBzjqU4APcqBFNAw==}
- '@cspell/dict-node@5.0.8':
- resolution: {integrity: sha512-AirZcN2i84ynev3p2/1NCPEhnNsHKMz9zciTngGoqpdItUb2bDt1nJBjwlsrFI78GZRph/VaqTVFwYikmncpXg==}
+ '@cspell/dict-node@5.0.9':
+ resolution: {integrity: sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==}
- '@cspell/dict-npm@5.2.29':
- resolution: {integrity: sha512-ZAef8JpYmbuHFT1zekj/YyImLPvZevjECw663EmG5GPePyNo4AfH8Dd2fFhaOyQ3P5I5LrkAhGwypnOfUxcssw==}
+ '@cspell/dict-npm@5.2.30':
+ resolution: {integrity: sha512-GHgl3wAkoi87y3AXE1Bogwt0wHCB3uydOx6p8ujjXg9Ba9twlOK2SzD6LrClHoWrnADuGZZIxLnesDA6GtlH4w==}
'@cspell/dict-people-names@1.1.16':
resolution: {integrity: sha512-jiV+V32DVdaMqpznnqqNNMNaKFtyaHnZvak7HrVLWulGgobilQk+8NzFO9mtkyDs7Pde7CEGSExBAvc+xZxgeA==}
@@ -472,9 +472,9 @@ snapshots:
'@cspell/dict-flutter': 1.1.1
'@cspell/dict-fonts': 4.0.5
'@cspell/dict-fsharp': 1.1.1
- '@cspell/dict-fullstack': 3.2.7
+ '@cspell/dict-fullstack': 3.2.8
'@cspell/dict-gaming-terms': 1.1.2
- '@cspell/dict-git': 3.0.7
+ '@cspell/dict-git': 3.1.0
'@cspell/dict-golang': 6.0.26
'@cspell/dict-google': 1.0.9
'@cspell/dict-haskell': 4.0.6
@@ -490,8 +490,8 @@ snapshots:
'@cspell/dict-makefile': 1.0.5
'@cspell/dict-markdown': 2.0.14(@cspell/dict-css@4.0.19)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.14)(@cspell/dict-typescript@3.2.3)
'@cspell/dict-monkeyc': 1.0.12
- '@cspell/dict-node': 5.0.8
- '@cspell/dict-npm': 5.2.29
+ '@cspell/dict-node': 5.0.9
+ '@cspell/dict-npm': 5.2.30
'@cspell/dict-php': 4.1.1
'@cspell/dict-powershell': 5.0.15
'@cspell/dict-public-licenses': 2.0.15
@@ -569,11 +569,11 @@ snapshots:
'@cspell/dict-fsharp@1.1.1': {}
- '@cspell/dict-fullstack@3.2.7': {}
+ '@cspell/dict-fullstack@3.2.8': {}
'@cspell/dict-gaming-terms@1.1.2': {}
- '@cspell/dict-git@3.0.7': {}
+ '@cspell/dict-git@3.1.0': {}
'@cspell/dict-golang@6.0.26': {}
@@ -610,9 +610,9 @@ snapshots:
'@cspell/dict-monkeyc@1.0.12': {}
- '@cspell/dict-node@5.0.8': {}
+ '@cspell/dict-node@5.0.9': {}
- '@cspell/dict-npm@5.2.29': {}
+ '@cspell/dict-npm@5.2.30': {}
'@cspell/dict-people-names@1.1.16': {}
diff --git a/docker-compose/local/compose.yaml b/docker-compose/local/compose.yaml
index 5d7a36265e..b7c94f401b 100644
--- a/docker-compose/local/compose.yaml
+++ b/docker-compose/local/compose.yaml
@@ -4,6 +4,7 @@ services:
command: >
sh -c '
python manage.py migrate &&
+ python manage.py clear_cache &&
python manage.py runserver 0.0.0.0:8000
'
image: nest-local-backend
@@ -23,7 +24,7 @@ services:
DJANGO_DB_PORT: ${DJANGO_DB_PORT:-5432}
DJANGO_DB_USER: ${DJANGO_DB_USER:-nest_user_dev}
DJANGO_REDIS_HOST: ${DJANGO_REDIS_HOST:-nest-cache}
- DJANGO_REDIS_PASSWORD: ${DJANGO_REDIS_HOST:-nest-cache-password}
+ DJANGO_REDIS_PASSWORD: ${DJANGO_REDIS_PASSWORD:-nest-cache-password}
networks:
- nest-network
ports:
diff --git a/docker/cspell/Dockerfile b/docker/cspell/Dockerfile
index 1e0069ca51..ae90478620 100644
--- a/docker/cspell/Dockerfile
+++ b/docker/cspell/Dockerfile
@@ -18,6 +18,6 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
WORKDIR /nest
-ENTRYPOINT ["/opt/node/node_modules/.bin/cspell"]
-
USER node
+
+ENTRYPOINT ["/opt/node/node_modules/.bin/cspell"]
diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile
index ebe729236f..85cb73d0db 100644
--- a/docker/frontend/Dockerfile
+++ b/docker/frontend/Dockerfile
@@ -48,17 +48,17 @@ WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
-# Fix CVE-2026-23745: Update npm's bundled tar from 7.5.1 to 7.5.3 in runner stage
+# Fix CVE-2026-23745: Update npm's bundled tar to 7.5.3 in runner stage
# Note: Must download tar with npm pack BEFORE removing the old tar (npm needs it)
RUN cd /tmp && \
- npm pack tar@7.5.3 && \
- tar -xzf tar-7.5.3.tgz && \
+ npm pack tar@7.5.4 && \
+ tar -xzf tar-7.5.4.tgz && \
TAR_DIR="/usr/local/lib/node_modules/npm/node_modules/tar" && \
rm -rf "${TAR_DIR}" && \
cp -r package "${TAR_DIR}" && \
chmod -R 755 "${TAR_DIR}" && \
- rm -rf package tar-7.5.3.tgz && \
- grep -q 'version.*7.5.3' "${TAR_DIR}/package.json"
+ rm -rf package tar-7.5.4.tgz && \
+ grep -q 'version.*7.5.4' "${TAR_DIR}/package.json"
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 -G nodejs nextjs
diff --git a/docker/frontend/Dockerfile.e2e.test b/docker/frontend/Dockerfile.e2e.test
index bd03a0130c..a66206cbc2 100644
--- a/docker/frontend/Dockerfile.e2e.test
+++ b/docker/frontend/Dockerfile.e2e.test
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/playwright:v1.57.0-jammy
+FROM mcr.microsoft.com/playwright:v1.58.0-jammy
ENV FORCE_COLOR=1 \
NPM_CACHE="/app/.npm" \
diff --git a/docker/semgrep/Dockerfile b/docker/semgrep/Dockerfile
new file mode 100644
index 0000000000..619c2058cf
--- /dev/null
+++ b/docker/semgrep/Dockerfile
@@ -0,0 +1 @@
+FROM semgrep/semgrep:1.148.0
diff --git a/docs/poetry.lock b/docs/poetry.lock
index 62ac200794..eda0da3ceb 100644
--- a/docs/poetry.lock
+++ b/docs/poetry.lock
@@ -283,18 +283,18 @@ files = [
[[package]]
name = "markdown"
-version = "3.10"
+version = "3.10.1"
description = "Python implementation of John Gruber's Markdown."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c"},
- {file = "markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e"},
+ {file = "markdown-3.10.1-py3-none-any.whl", hash = "sha256:867d788939fe33e4b736426f5b9f651ad0c0ae0ecf89df0ca5d1176c70812fe3"},
+ {file = "markdown-3.10.1.tar.gz", hash = "sha256:1c19c10bd5c14ac948c53d0d762a04e2fa35a6d58a6b7b1e6bfcbe6fefc0001a"},
]
[package.extras]
-docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
+docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python] (>=0.28.3)"]
testing = ["coverage", "pyyaml"]
[[package]]
@@ -535,14 +535,14 @@ mkdocs = ">=1.4.1"
[[package]]
name = "mkdocstrings"
-version = "1.0.0"
+version = "1.0.2"
description = "Automatic documentation from sources, for MkDocs."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "mkdocstrings-1.0.0-py3-none-any.whl", hash = "sha256:4c50eb960bff6e05dfc631f6bc00dfabffbcb29c5ff25f676d64daae05ed82fa"},
- {file = "mkdocstrings-1.0.0.tar.gz", hash = "sha256:351a006dbb27aefce241ade110d3cd040c1145b7a3eb5fd5ac23f03ed67f401a"},
+ {file = "mkdocstrings-1.0.2-py3-none-any.whl", hash = "sha256:41897815a8026c3634fe5d51472c3a569f92ded0ad8c7a640550873eea3b6817"},
+ {file = "mkdocstrings-1.0.2.tar.gz", hash = "sha256:48edd0ccbcb9e30a3121684e165261a9d6af4d63385fc4f39a54a49ac3b32ea8"},
]
[package.dependencies]
@@ -560,14 +560,14 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
[[package]]
name = "packaging"
-version = "25.0"
+version = "26.0"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
- {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"},
- {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"},
+ {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"},
+ {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"},
]
[[package]]
@@ -638,14 +638,14 @@ windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pymdown-extensions"
-version = "10.20"
+version = "10.20.1"
description = "Extension pack for Python Markdown."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "pymdown_extensions-10.20-py3-none-any.whl", hash = "sha256:ea9e62add865da80a271d00bfa1c0fa085b20d133fb3fc97afdc88e682f60b2f"},
- {file = "pymdown_extensions-10.20.tar.gz", hash = "sha256:5c73566ab0cf38c6ba084cb7c5ea64a119ae0500cce754ccb682761dfea13a52"},
+ {file = "pymdown_extensions-10.20.1-py3-none-any.whl", hash = "sha256:24af7feacbca56504b313b7b418c4f5e1317bb5fea60f03d57be7fcc40912aa0"},
+ {file = "pymdown_extensions-10.20.1.tar.gz", hash = "sha256:e7e39c865727338d434b55f1dd8da51febcffcaebd6e1a0b9c836243f660740a"},
]
[package.dependencies]
diff --git a/frontend/__tests__/a11y/components/ActionButton.a11y.test.tsx b/frontend/__tests__/a11y/components/ActionButton.a11y.test.tsx
index 802871689f..f0a3700137 100644
--- a/frontend/__tests__/a11y/components/ActionButton.a11y.test.tsx
+++ b/frontend/__tests__/a11y/components/ActionButton.a11y.test.tsx
@@ -1,9 +1,7 @@
import { render } from '@testing-library/react'
-import { axe, toHaveNoViolations } from 'jest-axe'
+import { axe } from 'jest-axe'
import ActionButton from 'components/ActionButton'
-expect.extend(toHaveNoViolations)
-
describe('ActionButton Accessibility', () => {
it('should not have any accessibility violations when no url is provided', async () => {
const { container } = render(
+
+ {metric.projectName === '' ? 'No name' : metric.projectName} +
+Score: {metric.score}
+{metric.starsCount}
-{metric.forksCount}
-{metric.contributorsCount}
-- {new Date(metric.createdAt).toLocaleString('default', { - month: 'short', - day: 'numeric', - year: 'numeric', - })} -
-{metric.score}
++ Stars +
++ {metric.starsCount} +
++ Forks +
++ {metric.forksCount} +
++ Contributors +
++ {metric.contributorsCount} +
++ Health Checked +
++ {new Date(metric.createdAt).toLocaleString('en-US', { + month: 'short', + day: 'numeric', + year: 'numeric', + })} +
+